Merge branch 'master' of https://code.google.com/p/plexi
diff --git a/build.xml b/build.xml
index 95b058c..9b4046c 100644
--- a/build.xml
+++ b/build.xml
@@ -76,13 +76,11 @@
<fileset dir="${lib.dir}">
<!--include name="guice-3.0.jar"/-->
<include name="jsr305.jar"/>
- <include name="servlet-api.jar"/>
<!-- Dependencies that are in common with opensaml. -->
<include name="joda-time-1.6.jar"/>
<include name="opensaml-2.3.2.jar"/>
<include name="openws-1.3.1.jar"/>
- <include name="slf4j-api-1.5.10.jar"/>
<include name="xmltooling-1.2.2.jar"/>
</fileset>
</path>
diff --git a/lib/servlet-api.jar b/lib/servlet-api.jar
deleted file mode 100644
index e76311f..0000000
--- a/lib/servlet-api.jar
+++ /dev/null
Binary files differ
diff --git a/src/com/google/common/base/Pair.java b/src/com/google/common/base/Pair.java
deleted file mode 100644
index 11b94cb..0000000
--- a/src/com/google/common/base/Pair.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Copyright (c) 2008 Google Inc.
- *
- * 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.google.common.base;
-
-import java.io.Serializable;
-/**
- * Pair is an expedient way to combine two arbitrary objects into one. <b>Its
- * use is not to be preferred</b> to creating a custom type, but it can be
- * handy in a pinch. If your {@link #equals}, {@link #hashCode},
- * {@link #toString}, and/or {@link #clone} behavior matter to you at all, you
- * may not want to use this (or you may at least wish to subclass).
- *
- *
-
- *
- * <p>This class may be used with the Google Web Toolkit (GWT).
- *
- */
-public class Pair<A,B> implements Serializable, Cloneable {
- private static final long serialVersionUID = 747826592375603043L;
-
- /** Creates a new pair containing the given objects in order. */
- public static <A,B> Pair<A,B> of(A first, B second) {
- return new Pair<A,B>(first, second);
- }
-
- /** The first element of the pair. */
- public final A first;
-
- /** The second element of the pair. */
- public final B second;
-
- /** Cumbersome way to create a new pair (see {@link #of}. */
- public Pair(A first, B second) {
- this.first = first;
- this.second = second;
- }
-
- /** Optional accessor method for {@link #first}. */
- public A getFirst() {
- return first;
- }
-
- /** Optional accessor method for {@link #second}. */
- public B getSecond() {
- return second;
- }
-
- @Override public Pair<A,B> clone() {
- try {
- @SuppressWarnings("unchecked")
- Pair<A,B> result = (Pair<A,B>) super.clone();
- return result;
- } catch (CloneNotSupportedException e) {
- throw new AssertionError(e);
-
-
-
-
-
- }
- }
-
- @Override public boolean equals(Object object) {
-
-
- if (object instanceof Pair<?,?>) {
- Pair<?,?> other = (Pair<?,?>) object;
- return eq(first, other.first) && eq(second, other.second);
- }
- return false;
- }
-
- @Override public int hashCode() {
- /*
- * This combination yields entropy comparable to constituent hashes
- * and ensures that hash(a,b) != hash(b,a).
- */
- return (hash(first, 0) + 0xDeadBeef) ^ hash(second, 0);
- }
-
- /**
- * This implementation returns the String representation of this pair in
- * the form {@code (string1, string2)}, where {@code string1} and
- * {@code string2} are the {@link Object#toString} representations of the
- * elements inside the pair.
- */
- @Override public String toString() {
- return String.format("(%s, %s)", first, second);
- }
-
-
- private static boolean eq(Object a, Object b) {
- return a == b || (a != null && a.equals(b));
- }
-
- private static int hash(Object object, int nullHash) {
- return (object == null) ? nullHash : object.hashCode();
- }
-}
diff --git a/src/com/google/common/labs/matcher/ParsedUrlPattern.java b/src/com/google/common/labs/matcher/ParsedUrlPattern.java
deleted file mode 100644
index 31812c9..0000000
--- a/src/com/google/common/labs/matcher/ParsedUrlPattern.java
+++ /dev/null
@@ -1,621 +0,0 @@
-// Copyright 2008 Google Inc.
-//
-// 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.google.common.labs.matcher;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import com.google.common.base.Preconditions;
-
-/**
- * This class parses a Google URL pattern into an immutable representation that
- * provides equivalent Java regexes,
- * exact-match patterns and prefix patterns, as appropriate. For a description
- * of Google URL patterns, see the
- * documentation in <a
- * href="http://code.google.com/apis/searchappliance/documentation/50/admin/URL_patterns.html">
- * this document</a>.
- * <p>
- * All Google URL patterns can be translated into an equivalent Java regex (with
- * some exceptions and caveats, see below). This class provides access to an
- * equivalent Java regex through {@link #getUrlRegex()}.
- * <p>
- * In addition, the class provides further analysis and special kinds of
- * patterns, depending on these top-level predicates:
- * <ul>
- * <li> {@link #isHostPathType()}: Returns {@code true} if the parsed pattern
- * is a "host-path" pattern. A "host-path" pattern is a pattern that can be
- * parsed into two regexes, a host regex and a path regex, such that a subject
- * URL matches the original URL pattern iff the host portion matches the host
- * regex and the path portion matches the path regex. If
- * {@code isHostPathType()} is true, then {@link #getHostRegex()} and
- * {@link #getPathRegex()} return the corresponding regexes. </li>
- * <li> {@link #isPathPrefixMatch()}: Returns {@code true} if the parsed
- * pattern is a "host-path" pattern and the path portion of the pattern is
- * simply a fixed string that must appear at the beginning of the path. In this
- * case, {@link #getPathPrefixString()} returns a simple string (not a regex)
- * that can be matched against the start of the subject URL's path. </li>
- * <li> {@link #isPathExactMatch()}: Returns {@code true} if if the parsed
- * pattern is a "host-path" pattern and the path portion of the pattern is an
- * exact-match string. In this case, {@link #getPathExactString()} returns a
- * simple string (not a regex) that can be matched exactly against the subject
- * URL's path. </li>
- * </ul>
- * In summary:
- * <ul>
- * <li> {@code getUrlRegex()} provides an equivalent Java regex for the entire
- * pattern. </li>
- * <li> If {@code isHostPathType()} is true, then, {@code getHostRegex()} and
- * {@code getPathRegex()} return regexes for the two portions.</li>
- * <li> If {@code isPrefixPathMatch()} is true, then,
- * {@code getPrefixPathMatchPattern()} returns a simple string pattern for
- * prefix match.</li>
- * <li> If {@code isPathExactMatch()} is true, then, in addition,
- * {@code getPathExactMatchPattern()} returns a simple string pattern for exact
- * match.
- * </ul>
- * <p>
- * Note: the "path" portion is the hierarchical part, that is, everything
- * following the first slash (not the {@code ://}). The "host" portion is
- * everything before that. For example: for the URL
- * {@code http://www.example.com/foo/bar}, the protocol-authority portion is
- * {@code http://www.example.com/} and the file portion is {@code /foo/bar}.
- * Note the the middle slash appears in both portions.
- * <p>
- * A parser is provided to separate a URL string into host and path portions:
- * {@link AnalyzedUrl}. You can access the host and path portions through
- * {@link AnalyzedUrl#getHostPart()} and {@link AnalyzedUrl#getPathPart()}. It
- * is recommended that this parser be used rather than the standard
- * {@code getHost()} and {@code getPath()} functions of {@link java.net.URL},
- * because this class and {@code AnalyzedUrl} share parsing infrastructure and
- * at present, there is at least one significant difference:
- * {@code AnalyzedUrl.getPathPart()} includes the leading slash but
- * {@code java.net.URL.getPath()} does not. TODO: fix this.
- * <p>
- * Exceptions and caveats: not all forms of Google URL patterns are currently
- * supported. At present, these exceptions and special cases apply:
- * <ul>
- * <li> {@code www?:} patterns are not supported </li>
- * <li> {@code regexp:} and {@code regexpCase:} patterns are translated simply
- * by removing those two prefixes. Thus, the remaining pattern is assumed to be
- * a Java regex, not a GNU regex (as documented on the <a
- * href="http://code.google.com/apis/searchappliance/documentation/50/admin/URL_patterns.html">
- * reference site</a>). </li>
- * <li> {@code regexpIgnoreCase:} patterns are handled similarly. In this case,
- * the prefix is removed and the pattern is enclosed in {@code (?i:}...{@code )}</li>
- * <li> Exception patterns (patterns with leading {@code -} or {@code +-}) are
- * not supported.</li>
- * </ul>
- */
-public class ParsedUrlPattern {
-
- private final String urlPattern;
- private final String urlRegex;
-
- private final boolean hostPathType;
- private final String hostRegex;
-
- private final String pathRegex;
- private final boolean pathExactMatch;
- private final String pathExactMatchPattern;
-
- private final boolean prefixPathMatch;
- private final String prefixPathMatchPattern;
-
- /**
- * Parses a Google URL pattern to Java regexes. Google URL patterns are
- * publicly documented <a
- * href="http://code.google.com/apis/searchappliance/documentation/50/admin/URL_patterns.html">
- * here </a>.
- *
- * @param urlPattern A Google URL pattern
- * @throws IllegalArgumentException if the URL pattern is unsupported or can
- * not be parsed
- */
- public ParsedUrlPattern(String urlPattern) {
- ParsedUrlPatternBuilder t = new ParsedUrlPatternBuilder(urlPattern);
- this.urlPattern = t.urlPattern;
- this.urlRegex = t.urlRegex;
- this.hostPathType = t.hostPathType;
- this.hostRegex = t.hostRegex;
- this.pathRegex = t.pathRegex;
- this.pathExactMatch = t.pathExactMatch;
- this.pathExactMatchPattern = t.pathExactMatchPattern;
- this.prefixPathMatch = t.prefixPathMatch;
- this.prefixPathMatchPattern = t.prefixPathMatchPattern;
-
- }
-
- /**
- * Returns a regex that matches the entire URL. A subject string matches the
- * URL pattern iff it matches this regex.
- *
- * @return a regex that matches the entire URL
- */
- public String getUrlRegex() {
- return urlRegex;
- }
-
- /**
- * Returns {@code true} if the parsed pattern is a "host-path" pattern. A
- * "host-path" pattern is a pattern that can be parsed into two regexes, a
- * host regex and a path regex, such that a subject url matches the pattern
- * iff the host portion matches the host regex and the path portion matches
- * the path regex.
- * <p>
- * For example, the pattern {@code example.com/foo} might be parsed into two
- * regexes, host regex: {@code example.com/$} and path regex: {@code ^/foo}.
- */
- public boolean isHostPathType() {
- return hostPathType;
- }
-
- /**
- * Returns a regex that matches the host (protocol and authority) portion of
- * the URL. If this is a host-path regex then a subject string matches the url
- * pattern iff the host portion matches this regex and the the path portion
- * matches the corresponding path regex (obtained by {@link #getPathRegex()}).
- * <p>
- * This should be used against URLs that have been parsed using the
- * {@link AnalyzedUrl} class.
- * <p>
- * Note: this should only be used if {@code isHostPathType()} is true; if not,
- * then this method throws an {@code IllegalStateException}.
- *
- * @return a regex that matches the host (protocol and authority) portion of
- * the URL
- * @throws IllegalStateException if {@code isHostPathType()} is false
- */
- public String getHostRegex() {
- Preconditions.checkState(isHostPathType());
- return hostRegex;
- }
-
- /**
- * Returns a regex that matches the path (hierarchical) portion of the URL.
- * <p>
- * This should be used against URLs that have been parsed using the
- * {@link AnalyzedUrl} class.
- * <p>
- * Note: this should only be used if {@link #isHostPathType()} is true; if
- * not, then this method throws an {@code IllegalStateException}.
- *
- * @return a regex that matches the path (hierarchical) portion of the URL
- * @throws IllegalStateException if {@code isHostPathType()} is false
- */
- public String getPathRegex() {
- Preconditions.checkState(isHostPathType());
- return pathRegex;
- }
-
- /**
- * Indicates whether the parsed pattern gives a prefix match pattern. If this
- * is true, then this pattern can be obtained using
- * {@link #getPathPrefixString()}.
- *
- * @return {@code true} if the parsed pattern gives an prefix match pattern.
- */
- public boolean isPathPrefixMatch() {
- return prefixPathMatch;
- }
-
- /**
- * If {@link #isPathPrefixMatch()} is true, then this returns a simple string
- * that can be matched against the path portion of a subject string using
- * {@link String#startsWith(String)}.
- * <p>
- * Note: this should only be used if {@code isPrefixPathMatch()} is true; if
- * not, then this method throws an {@code IllegalStateException}.
- *
- * @return a string that matches a prefix of the path portion of the URL
- * @throws IllegalStateException if {@code isPathPrefixMatch()} is false
- */
- public String getPathPrefixString() {
- Preconditions.checkState(isPathPrefixMatch());
- return prefixPathMatchPattern;
- }
-
- /**
- * Returns whether the parsed pattern gives an exact match pattern. If this is
- * true, then this pattern can be obtained using {@link #getPathExactString()}.
- *
- * @return {@code true} if the parsed pattern gives an exact match pattern.
- */
- public boolean isPathExactMatch() {
- return pathExactMatch;
- }
-
- /**
- * If {@link #isPathExactMatch()} is true, then this returns a simple string
- * that can be matched against the path portion of a subject string using
- * {@link String#equals(Object)}. Note: this should only be used if
- * {@code isPathExactMatch()} is true; if not, then this method throws an
- * {@code IllegalStateException}.
- *
- * @return a string that matches the entire path
- * @throws IllegalStateException if {@code isPathExactMatch()} is false
- */
- public String getPathExactString() {
- Preconditions.checkState(isPathExactMatch());
- return pathExactMatchPattern;
- }
-
- /**
- * Returns the original URL pattern.
- *
- * @return the original URL pattern.
- */
- public String getUrlPattern() {
- return urlPattern;
- }
-
- // This is the master meta-regex. This is used both for parsing URL patterns
- // and for parsing URLs
- private static final String URL_METAPATTERN_STRING =
- "\\A(\\^)?((?:([^/:$<]*)((?:(?::|(?::/))?\\Z)|(?:://)))?" +
- // ___1_____2a__3_________4b__c____d____________e
- "(?:([^/:@]*)@)?([^/:<]*)?(?::([^/<]*))?)(/|(?:</>))?(?:(.*?)(\\Z|\\$)?)?\\Z"
- // f__5___________6_________g___7__________8__h________i__9____0
- ;
-
- // Groups: (capturing groups are numbered, non-capturing are lettered)
- // 1 anchor (^)
- // 2 protocol + authority (not including /)
- // a protocol + ((nothing or : or :/ followed by end of pattern) or ::/)
- // 3 protocol
- // 4 protocol separator ((nothing or : or :/ followed by end of pattern) or
- // ::/)
- // b nothing or : or :/ followed by end of pattern
- // c : or :/
- // d :/
- // e ::/
- // f userinfo + @
- // 5 userinfo
- // 6 host
- // g : + port
- // 7 port
- // 8 slash (after authority) (could be a slash or "</>")
- // h </>
- // i file + anchor
- // 9 file
- // 10 anchor ($)
-
- // This Pattern is package visible so it can be used by AnalyzedUrl
- static final Pattern URL_METAPATTERN = Pattern.compile(URL_METAPATTERN_STRING);
-
- // As above, the enum is package visible so it can be used by AnalyzedUrl
- // Note: if you change the master regex, you should change this enum to match
- static enum MetaRegexGroup {
- LEFT_ANCHOR(1), PROTOCOL_AUTHORITY(2), PROTOCOL(3), PROTOCOL_SEPARATOR(4), USERINFO(5),
- HOST(6), PORT(7), SLASH_AFTER_AUTHORITY(8), FILE(9), RIGHT_ANCHOR(10);
- private int n;
-
- MetaRegexGroup(int n) {
- this.n = n;
- }
-
- int intValue() {
- return n;
- }
- }
-
- // This static helper is also shared with the AnalyzedUrl
- static String getGroup(Matcher m, MetaRegexGroup g) {
- String s = m.group(g.intValue());
- return (s == null) ? "" : s;
- }
-
- private static class ParsedUrlPatternBuilder {
-
- public String urlPattern;
- public String urlRegex;
-
- public boolean hostPathType;
- public String hostRegex;
-
- public String pathRegex;
- public boolean pathExactMatch;
- public String pathExactMatchPattern;
-
- public boolean prefixPathMatch;
- public String prefixPathMatchPattern;
-
- ParsedUrlPatternBuilder(String urlPattern) {
- checkPatternValidity(urlPattern);
- this.urlPattern = urlPattern;
- analyze();
- }
-
- private void analyze() {
- if (urlPattern.startsWith(CONTAINS_PATTERNS_METAPATTERN_PREFIX)) {
- urlRegex =
- Pattern.quote(urlPattern.substring(CONTAINS_PATTERNS_METAPATTERN_PREFIX.length()));
- initNonHostPathPattern();
- return;
- }
-
- if (urlPattern.startsWith(REGEXP_PATTERNS_METAPATTERN_PREFIX)) {
- urlRegex = urlPattern.substring(REGEXP_PATTERNS_METAPATTERN_PREFIX.length());
- initNonHostPathPattern();
- return;
- }
-
- if (urlPattern.startsWith(REGEXPCASE_PATTERNS_METAPATTERN_PREFIX)) {
- urlRegex = urlPattern.substring(REGEXPCASE_PATTERNS_METAPATTERN_PREFIX.length());
- initNonHostPathPattern();
- return;
- }
-
- if (urlPattern.startsWith(REGEXPIGNORECASE_PATTERNS_METAPATTERN_PREFIX)) {
- urlRegex =
- "(?i:" + urlPattern.substring(REGEXPIGNORECASE_PATTERNS_METAPATTERN_PREFIX.length())
- + ")";
- initNonHostPathPattern();
- return;
- }
-
- initHostPathPattern();
-
- if (isNullOrEmpty(urlPattern)) {
- prefixPathMatch = true;
- return;
- }
- if (testForAndHandleNoSlashSuffixPattern()) {
- return;
- }
- Matcher m = URL_METAPATTERN.matcher(urlPattern);
- Preconditions.checkArgument(m.find(), "problem parsing urlpattern: " + urlPattern);
- urlRegex = buildUrlRegex(m);
- pathRegex = buildPathRegex(m);
- hostRegex = buildHostRegex(m);
- }
-
- private void initNonHostPathPattern() {
- hostPathType = false;
- pathRegex = null;
- hostRegex = null;
- pathExactMatch = false;
- pathExactMatchPattern = null;
- prefixPathMatch = false;
- prefixPathMatchPattern = null;
- }
-
- private void initHostPathPattern() {
- hostPathType = true;
- urlRegex = "";
- pathRegex = "";
- hostRegex = "";
- pathExactMatch = false;
- pathExactMatchPattern = null;
- prefixPathMatch = false;
- prefixPathMatchPattern = "/";
- }
-
- // A suffix pattern (ends in $) that has no slash just doesn't parse well
- // with
- // the metapattern. So we use a special pattern for this case.
- private boolean testForAndHandleNoSlashSuffixPattern() {
- Matcher m = NO_SLASH_SUFFIX_PATTERN.matcher(urlPattern);
- if (!m.find()) {
- return false;
- }
- urlRegex = Pattern.quote(m.group(1)) + OUTPUT_RIGHT_ANCHOR_PATTERN_STRING;
- pathRegex = urlRegex;
- hostRegex = "";
- pathExactMatch = false;
- pathExactMatchPattern = null;
- prefixPathMatch = false;
- prefixPathMatchPattern = null;
- return true;
- }
-
- // suffix patterns that contain no slash jam up my master meta-regex: the
- // string before the $ gets put in the wrong capturing group. I fought with
- // it
- // a while but then bailed and just made a special meta-regex for them
- private static final String NO_SLASH_SUFFIX_PATTERN_STRING = "\\A([^/]*)\\$\\Z";
- private static final Pattern NO_SLASH_SUFFIX_PATTERN =
- Pattern.compile(NO_SLASH_SUFFIX_PATTERN_STRING);
-
- private static final String CONTAINS_PATTERNS_METAPATTERN_PREFIX = "contains:";
-
- private static final String REGEXP_PATTERNS_METAPATTERN_PREFIX = "regexp:";
-
- private static final String REGEXPCASE_PATTERNS_METAPATTERN_PREFIX = "regexpCase:";
-
- private static final String REGEXPIGNORECASE_PATTERNS_METAPATTERN_PREFIX = "regexpIgnoreCase:";
-
- private static final String UNSUPPORTED_PATTERNS_METAPATTERN_STRING = "\\A(?:(www\\?:)|(-))";
- private static final Pattern UNSUPPORTED_PATTERNS_METAPATTERN =
- Pattern.compile(UNSUPPORTED_PATTERNS_METAPATTERN_STRING);
-
- private static final String OUTPUT_RIGHT_ANCHOR_PATTERN_STRING = "\\Z";
- private static final String OUTPUT_LEFT_ANCHOR_PATTERN_STRING = "\\A";
-
- private static final String OUTPUT_SLASH = "/";
- private static final String OUTPUT_ANY_OR_NO_PORT_PATTERN = "(\\:[^/]*)?";
- private static final String OUTPUT_ANY_PORT_PATTERN = "\\:[^/]*";
-
- private static boolean isNullOrEmpty(String s) {
- return (s == null || s.length() < 1);
- }
-
- // These helper functions whose names match buildSOMETHINGPattern build a
- // regex to match the SOMETHING in their names. They should be usable,
- // appropriately quoted regexes
- private static String buildProtocolUserinfoHostPattern(Matcher m) {
- StringBuilder sb = new StringBuilder();
- sb.append(getGroup(m, MetaRegexGroup.PROTOCOL));
- sb.append(getGroup(m, MetaRegexGroup.PROTOCOL_SEPARATOR));
- String userInfo = getGroup(m, MetaRegexGroup.USERINFO);
- if (!isNullOrEmpty(userInfo)) {
- sb.append(userInfo);
- sb.append("@");
- }
- sb.append(getGroup(m, MetaRegexGroup.HOST));
- String unquotedPattern = sb.toString();
- return isNullOrEmpty(unquotedPattern) ? "" : Pattern.quote(unquotedPattern);
- }
-
- // port is tricky because the absence of a port in a pattern should match
- // any
- // specific port in a target
- private static String buildPortPattern(Matcher m) {
- StringBuilder sb = new StringBuilder();
- String port = getGroup(m, MetaRegexGroup.PORT);
- if (isNullOrEmpty(port)) {
- // port was empty - match any port - default or explicit
- sb.append(OUTPUT_ANY_OR_NO_PORT_PATTERN);
- } else {
- if (port.equals("*")) {
- // port was explicitly "*" - match any explicitly specified port
- sb.append(OUTPUT_ANY_PORT_PATTERN);
- } else {
- // port was explicit and not "*" - match only that port
- sb.append("\\:");
- sb.append(Pattern.quote(port));
- }
- }
- return sb.toString();
- }
-
- private static String buildUnquotedFilePattern(Matcher m) {
- return getGroup(m, MetaRegexGroup.FILE);
- }
-
- private static String buildQuotedFilePattern(Matcher m) {
- String unquotedPattern = buildUnquotedFilePattern(m);
- return isNullOrEmpty(unquotedPattern) ? "" : Pattern.quote(unquotedPattern);
- }
-
- // the helper functions whose names match buildSOMETHINGRegex each build one
- // of the three public regexes: the urlRegex, the protocolAuthorityRegex and
- // the fileRegex.
-
- // The main reason that the urlRegex is not simply the concatenation of the
- // protocolAuthorityRegex and the fileRegex is the anchors. Both for
- // correctness and efficiency, we want to use anchors only where
- // appropriate:
- // using ^A.*foo is considerably slower than just using foo.
- private String buildUrlRegex(Matcher m) {
- StringBuilder sb = new StringBuilder();
- String leftAnchor = getGroup(m, MetaRegexGroup.LEFT_ANCHOR);
- String protocolUserinfoHostPattern = buildProtocolUserinfoHostPattern(m);
- String portPattern = buildPortPattern(m);
- String slashAfterAuthority = getGroup(m, MetaRegexGroup.SLASH_AFTER_AUTHORITY);
- String filePattern = buildQuotedFilePattern(m);
- String rightAnchor = getGroup(m, MetaRegexGroup.RIGHT_ANCHOR);
- // prefix patterns need to be handled specially
- if (!isNullOrEmpty(leftAnchor)) {
- sb.append(OUTPUT_LEFT_ANCHOR_PATTERN_STRING);
- }
- if (!isNullOrEmpty(protocolUserinfoHostPattern)) {
- sb.append(protocolUserinfoHostPattern);
- }
- if (!isNullOrEmpty(portPattern)) {
- if (sb.length() > 0) {
- sb.append(portPattern);
- }
- }
- if (!isNullOrEmpty(slashAfterAuthority)) {
- if ("</>".equals(slashAfterAuthority)) {
- if (sb.length() < 1) {
- sb.append(OUTPUT_LEFT_ANCHOR_PATTERN_STRING);
- sb.append("[^/]*//[^/]*");
- }
- }
- sb.append(OUTPUT_SLASH);
- }
- if (!isNullOrEmpty(filePattern)) {
- sb.append(filePattern);
- }
- if (!isNullOrEmpty(rightAnchor)) {
- sb.append(rightAnchor);
- }
- return sb.toString();
- }
-
- private String buildHostRegex(Matcher m) {
- StringBuilder sb = new StringBuilder();
- String leftAnchor = getGroup(m, MetaRegexGroup.LEFT_ANCHOR);
- String protocolUserinfoHostPattern = buildProtocolUserinfoHostPattern(m);
- String portPattern = buildPortPattern(m);
- String slashAfterAuthority = getGroup(m, MetaRegexGroup.SLASH_AFTER_AUTHORITY);
- // prefix patterns need to be handled specially
- if (!isNullOrEmpty(leftAnchor)) {
- sb.append(OUTPUT_LEFT_ANCHOR_PATTERN_STRING);
- }
- if (!isNullOrEmpty(protocolUserinfoHostPattern)) {
- sb.append(protocolUserinfoHostPattern);
- }
- if (!isNullOrEmpty(portPattern)) {
- sb.append(portPattern);
- }
- if (!isNullOrEmpty(slashAfterAuthority)) {
- sb.append(OUTPUT_SLASH);
- }
- return sb.toString();
- }
-
- // We expect that, in practice, the fileRegex will be used much more often
- // than the protocolAuthority regex (there will probably be a hashtable for
- // the protocol-authority portion), so we really want to makes sure that the
- // fileRegexes are simple prefix matches, as often as possible.
- private String buildPathRegex(Matcher m) {
- boolean hasLeftAnchor = false;
- boolean hasRightAnchor = false;
- StringBuilder sb = new StringBuilder();
- String protocolAuthority = getGroup(m, MetaRegexGroup.PROTOCOL_AUTHORITY);
- String slashAfterAuthority = getGroup(m, MetaRegexGroup.SLASH_AFTER_AUTHORITY);
- String unquotedFilePattern = buildUnquotedFilePattern(m);
- String rightAnchor = getGroup(m, MetaRegexGroup.RIGHT_ANCHOR);
- // two conditions for this being an prefix pattern:
- // either there was a protocolAuthority OR there was a </>
- // slashAfterAuthority
- if (!isNullOrEmpty(protocolAuthority) || "</>".equals(slashAfterAuthority)) {
- hasLeftAnchor = true;
- sb.append(OUTPUT_LEFT_ANCHOR_PATTERN_STRING);
- }
- if (!isNullOrEmpty(slashAfterAuthority)) {
- sb.append(OUTPUT_SLASH);
- }
- sb.append(Pattern.quote(unquotedFilePattern));
- if (!isNullOrEmpty(rightAnchor)) {
- hasRightAnchor = true;
- sb.append(OUTPUT_RIGHT_ANCHOR_PATTERN_STRING);
- }
- if (hasLeftAnchor) {
- if (hasRightAnchor) {
- this.pathExactMatch = true;
- this.pathExactMatchPattern = "/" + unquotedFilePattern;
- this.prefixPathMatch = false;
- this.prefixPathMatchPattern = null;
- } else {
- this.pathExactMatch = false;
- this.pathExactMatchPattern = null;
- this.prefixPathMatch = true;
- this.prefixPathMatchPattern = "/" + unquotedFilePattern;
- }
- }
- return sb.toString();
- }
-
- private static void checkPatternValidity(String s) {
- Preconditions.checkNotNull(s);
- Matcher m = UNSUPPORTED_PATTERNS_METAPATTERN.matcher(s);
- Preconditions.checkArgument(!m.find(), "unsupported urlpattern: " + s);
- }
- }
-}
diff --git a/src/com/google/common/util/concurrent/BoundedExecutorService.java b/src/com/google/common/util/concurrent/BoundedExecutorService.java
deleted file mode 100644
index 12dd84a..0000000
--- a/src/com/google/common/util/concurrent/BoundedExecutorService.java
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// 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.google.common.util.concurrent;
-
-import java.util.List;
-import java.util.concurrent.*;
-
-/**
- * Trash class to allow code to compile unmodified.
- */
-public class BoundedExecutorService extends AbstractExecutorService {
- public BoundedExecutorService(Object ... params) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean awaitTermination(long timeout, TimeUnit unit) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isShutdown() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isTerminated() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void shutdown() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public List<Runnable> shutdownNow() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void execute(Runnable command) {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/src/com/google/enterprise/adaptor/CronScheduler.java b/src/com/google/enterprise/adaptor/CronScheduler.java
index 1cf3335..f0f260a 100644
--- a/src/com/google/enterprise/adaptor/CronScheduler.java
+++ b/src/com/google/enterprise/adaptor/CronScheduler.java
@@ -163,7 +163,8 @@
}
private static class CronPattern {
- private static final List<Field> FIELDS = Arrays.asList(Field.values());
+ private static final List<Field> FIELDS
+ = Collections.unmodifiableList(Arrays.asList(Field.values()));
private static enum Field {
MINUTE(0, 60, Calendar.MINUTE, 0),
@@ -216,27 +217,46 @@
// day of month: 0-30, 0 is 1st day of month.
// month: 0-11, 0 in January.
// day of week: 0-6, 0 is Sunday.
- private final List<BitSet> fields;
+ // null for any value implies wildcard
+ private final EnumMap<Field, BitSet> fields;
- private CronPattern(List<BitSet> fields) {
+ private CronPattern(EnumMap<Field, BitSet> fields) {
this.fields = fields;
}
public boolean matches(Date date, TimeZone timeZone) {
GregorianCalendar calendar = new GregorianCalendar(timeZone);
calendar.setTime(date);
- for (int i = 0; i < FIELDS.size(); i++) {
- Field field = FIELDS.get(i);
- if (!fields.get(i).get(field.calendarToIndex(calendar))) {
- return false;
- }
+ boolean dayMatches;
+ if (fields.get(Field.DAY_OF_MONTH) != null
+ && fields.get(Field.DAY_OF_WEEK) != null) {
+ // Both day of month and day of week are restricted, so we OR the two
+ // instead of the typical AND. This is a special case of the cron
+ // format since both fields restrict the day.
+ dayMatches = matches(Field.DAY_OF_MONTH, calendar)
+ || matches(Field.DAY_OF_WEEK, calendar);
+ } else {
+ dayMatches = matches(Field.DAY_OF_MONTH, calendar)
+ && matches(Field.DAY_OF_WEEK, calendar);
}
- return true;
+ return dayMatches
+ && matches(Field.MINUTE, calendar)
+ && matches(Field.HOUR, calendar)
+ && matches(Field.MONTH, calendar);
+ }
+
+ private boolean matches(Field field, Calendar calendar) {
+ BitSet bitset = fields.get(field);
+ if (bitset == null) {
+ // Wildcard.
+ return true;
+ }
+ return bitset.get(field.calendarToIndex(calendar));
}
@Override
public String toString() {
- return "" + fields;
+ return "" + fields.values();
}
public static CronPattern create(String timeSpecification)
@@ -248,10 +268,15 @@
"Should have precisely 5 fields: "
+ "minute, hour, day of month, month, day of week");
}
- List<BitSet> fields = new ArrayList<BitSet>(FIELDS.size());
- for (int i = 0; i < FIELDS.size(); i++) {
- String stringField = stringFields[i];
- Field fieldType = FIELDS.get(i);
+ EnumMap<Field, BitSet> fields = new EnumMap<Field, BitSet>(Field.class);
+ for (Field fieldType : FIELDS) {
+ String stringField = stringFields[fieldType.ordinal()];
+ if ("*".equals(stringField)) {
+ // Signal wildcard. Semantics of day of week and day of month vary
+ // based on raw wildcard vs any other value.
+ fields.put(fieldType, null);
+ continue;
+ }
BitSet set = new BitSet(fieldType.numValues());
for (String element : stringField.split(",", -1)) {
int step = 1;
@@ -282,7 +307,7 @@
}
}
}
- fields.add(set);
+ fields.put(fieldType, set);
}
return new CronPattern(fields);
}
diff --git a/src/com/google/enterprise/adaptor/HttpClientAdapter.java b/src/com/google/enterprise/adaptor/HttpClientAdapter.java
index 2b56d3e..ae46b16 100644
--- a/src/com/google/enterprise/adaptor/HttpClientAdapter.java
+++ b/src/com/google/enterprise/adaptor/HttpClientAdapter.java
@@ -15,8 +15,6 @@
package com.google.enterprise.adaptor;
import com.google.common.collect.ListMultimap;
-import com.google.enterprise.secmgr.common.CookieStore;
-import com.google.enterprise.secmgr.common.GCookie;
import com.google.enterprise.secmgr.http.HttpClientInterface;
import com.google.enterprise.secmgr.http.HttpExchange;
@@ -39,16 +37,6 @@
private static final String POST_ENCODING = "UTF-8";
@Override
- public HttpExchange headExchange(URL url) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public HttpExchange getExchange(URL url) {
- throw new UnsupportedOperationException();
- }
-
- @Override
public HttpExchange postExchange(URL url,
ListMultimap<String, String> parameters) {
HttpExchange exchange = new ClientExchange(url, "POST");
@@ -64,42 +52,6 @@
return exchange;
}
- @Override
- public HttpExchange newHttpExchange(URL url) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Connection getConnection(URL url) throws IOException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public HttpExchange headExchange(Connection connection, URL url) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public HttpExchange getExchange(Connection connection, URL url) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public HttpExchange postExchange(Connection connection, URL url,
- ListMultimap<String, String> parameters) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public HttpExchange newHttpExchange(Connection connection, URL url) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setRequestTimeoutMillis(int millisec) {
- throw new UnsupportedOperationException();
- }
-
private static class ClientExchange implements HttpExchange {
private final URL url;
private final String method;
@@ -182,16 +134,6 @@
return conn.getRequestProperty(headerName);
}
- @Override
- public void addCookies(Iterable<GCookie> cookies) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public CookieStore getCookies() {
- throw new UnsupportedOperationException();
- }
-
/** Does not copy provided byte array. */
@Override
public void setRequestBody(byte[] byteArrayRequestEntity) {
diff --git a/src/com/google/enterprise/adaptor/SecurityManagerConfig.java b/src/com/google/enterprise/adaptor/SecurityManagerConfig.java
index 813825f..d714a86 100644
--- a/src/com/google/enterprise/adaptor/SecurityManagerConfig.java
+++ b/src/com/google/enterprise/adaptor/SecurityManagerConfig.java
@@ -14,11 +14,8 @@
package com.google.enterprise.adaptor;
-import com.google.enterprise.secmgr.authncontroller.AuthnGuiceModule;
-import com.google.enterprise.secmgr.common.GCookie;
-import com.google.enterprise.secmgr.config.ConfigModule;
+import com.google.enterprise.secmgr.authncontroller.ExportedState;
import com.google.enterprise.secmgr.config.ConfigSingleton;
-import com.google.enterprise.secmgr.identity.CredentialModule;
import com.google.gson.GsonBuilder;
class SecurityManagerConfig {
@@ -27,10 +24,7 @@
new ConfigSingleton.GsonRegistrations() {
@Override
public void register(GsonBuilder builder) {
- AuthnGuiceModule.registerTypeAdapters(builder);
- ConfigModule.registerTypeAdapters(builder);
- CredentialModule.registerTypeAdapters(builder);
- GCookie.registerTypeAdapters(builder);
+ ExportedState.registerTypeAdapters(builder);
}
});
}
diff --git a/src/com/google/enterprise/secmgr/authncontroller/AuthnGuiceModule.java b/src/com/google/enterprise/secmgr/authncontroller/AuthnGuiceModule.java
deleted file mode 100644
index eac2824..0000000
--- a/src/com/google/enterprise/secmgr/authncontroller/AuthnGuiceModule.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.authncontroller;
-
-import com.google.gson.GsonBuilder;
-/*import com.google.inject.AbstractModule;*/
-
-/**
- * Guice configuration for this package.
- */
-public final class AuthnGuiceModule /*extends AbstractModule*/ {
-
- /*@Override
- protected void configure() {
- bind(AuthnController.class);
- bind(AuthnSessionManager.class).to(AuthnSessionManagerImpl.class);
- requestStaticInjection(AuthnSession.class);
- }*/
-
- public static void registerTypeAdapters(GsonBuilder builder) {
- AuthnSessionState.registerTypeAdapters(builder);
- ExportedState.registerTypeAdapters(builder);
- }
-}
diff --git a/src/com/google/enterprise/secmgr/authncontroller/AuthnSessionState.java b/src/com/google/enterprise/secmgr/authncontroller/AuthnSessionState.java
deleted file mode 100644
index b0d513f..0000000
--- a/src/com/google/enterprise/secmgr/authncontroller/AuthnSessionState.java
+++ /dev/null
@@ -1,858 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.google.enterprise.secmgr.authncontroller;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.google.common.collect.SetMultimap;
-import com.google.enterprise.secmgr.common.Chain;
-import com.google.enterprise.secmgr.common.CookieStore;
-import com.google.enterprise.secmgr.common.GCookie;
-import com.google.enterprise.secmgr.common.SecurityManagerUtil;
-import com.google.enterprise.secmgr.config.AuthnAuthority;
-import com.google.enterprise.secmgr.config.AuthnMechanism;
-import com.google.enterprise.secmgr.config.CredentialGroup;
-import com.google.enterprise.secmgr.identity.AbstractCredential;
-import com.google.enterprise.secmgr.identity.Credential;
-import com.google.enterprise.secmgr.identity.Verification;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-
-import java.lang.reflect.Type;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-import javax.annotation.concurrent.NotThreadSafe;
-
-/**
- * A representation of the state stored in an authentication session. This is
- * not the AuthnState that's used to keep track of the what the controller is
- * doing; this is the credentials gathered by the controller.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class AuthnSessionState {
-
- /**
- * The possible instruction operations supported here.
- */
- public static enum Operation {
- ADD_COOKIE(GCookie.class),
- ADD_CREDENTIAL(Credential.class),
- ADD_VERIFICATION(Verification.class),
- REMOVE_COOKIE(GCookie.class),
- REMOVE_CREDENTIAL(Credential.class),
- REMOVE_VERIFICATION(Verification.class);
-
- @Nonnull private final Class<?> operandClass;
-
- private Operation(Class<?> operandClass) {
- Preconditions.checkNotNull(operandClass);
- this.operandClass = operandClass;
- }
-
- @CheckReturnValue
- @Nonnull
- public Class<?> getOperandClass() {
- return operandClass;
- }
- }
-
- private static final AuthnSessionState EMPTY = new AuthnSessionState(Chain.<Instruction>empty());
-
- @Nonnull private final Chain<Instruction> instructions;
-
- private AuthnSessionState(Chain<Instruction> instructions) {
- Preconditions.checkNotNull(instructions);
- this.instructions = instructions;
- }
-
- /**
- * Gets an empty session state.
- */
- @CheckReturnValue
- @Nonnull
- public static AuthnSessionState empty() {
- return EMPTY;
- }
-
- /**
- * Gets a new session state with only the given verification.
- *
- * @param authority The authority that performed the verification process.
- * @param verification The verification that the state will hold.
- * @return A new state with that verification.
- */
- @CheckReturnValue
- @Nonnull
- public static AuthnSessionState of(AuthnAuthority authority, Verification verification) {
- return empty().addVerification(authority, verification);
- }
-
- @VisibleForTesting
- static AuthnSessionState of(Iterable<Instruction> instructions) {
- return new AuthnSessionState(Chain.copyOf(instructions));
- }
-
- @VisibleForTesting
- List<Instruction> getInstructions() {
- return instructions.toList();
- }
-
- /**
- * Is this state object empty?
- *
- * @return True only if there are no elements in this state.
- */
- @CheckReturnValue
- public boolean isEmpty() {
- return instructions.isEmpty();
- }
-
- /**
- * Unit testing relies on this; it's not used in production.
- */
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof AuthnSessionState)) { return false; }
- AuthnSessionState other = (AuthnSessionState) object;
- return Objects.equal(instructions, other.instructions);
- }
-
- /**
- * Unit testing relies on this; it's not used in production.
- */
- @Override
- public int hashCode() {
- return Objects.hashCode(instructions);
- }
-
- /**
- * Unit testing uses this for failure reporting; it's not used in production.
- */
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- for (Instruction instruction : getInstructions()) {
- builder.append(" ");
- builder.append(instruction);
- builder.append("\n");
- }
- return builder.toString();
- }
-
- /**
- * Appends some state to this state.
- *
- * @param delta The state to append
- * @return A new state with that state appended.
- */
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState add(AuthnSessionState delta) {
- return new AuthnSessionState(instructions.addAll(delta.getInstructions()));
- }
-
- /**
- * Gets a session state that represents the delta between this state and a
- * given one. For a given ancestor state {@code A}, it is always true that
- * {@code this.equals(A.add(this.getDelta(A)))}.
- *
- * @param ancestor The ancestor state to use as a reference.
- * @return A new state with instructions that have been added since the
- * ancestor.
- */
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState getDelta(AuthnSessionState ancestor) {
- return AuthnSessionState.of(instructions.toList(ancestor.instructions));
- }
-
- @CheckReturnValue
- private AuthnSessionState addInstruction(Instruction instruction) {
- Preconditions.checkNotNull(instruction);
- return new AuthnSessionState(instructions.add(instruction));
- }
-
- /**
- * Adds a cookie to this state.
- *
- * @param authority The authority from which the cookie was received.
- * @param cookie The cookie to be added.
- */
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState addCookie(AuthnAuthority authority, GCookie cookie) {
- return addInstruction(Instruction.make(Operation.ADD_COOKIE, authority, cookie));
- }
-
- /**
- * Adds some cookies to this state.
- *
- * @param authority The authority from which the cookie was received.
- * @param cookies The cookies to be added.
- */
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState addCookies(AuthnAuthority authority, Iterable<GCookie> cookies) {
- AuthnSessionState state = this;
- for (GCookie cookie : cookies) {
- state = state.addCookie(authority, cookie);
- }
- return state;
- }
-
- /**
- * Removes a cookie from this state.
- *
- * @param authority The authority from which the cookie was originally received.
- * @param cookie The cookie to be removed.
- */
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState removeCookie(AuthnAuthority authority, GCookie cookie) {
- return addInstruction(Instruction.make(Operation.REMOVE_COOKIE, authority, cookie));
- }
-
- /**
- * Removes some cookies from this state.
- *
- * @param authority The authority from which the cookie was received.
- * @param cookies The cookies to be removed.
- */
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState removeCookies(AuthnAuthority authority, Iterable<GCookie> cookies) {
- AuthnSessionState state = this;
- for (GCookie cookie : cookies) {
- state = state.removeCookie(authority, cookie);
- }
- return state;
- }
-
- /**
- * Adds a credential to this state.
- *
- * @param authority The authority from which the credential was received.
- * @param credential The credential to be added.
- */
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState addCredential(AuthnAuthority authority, Credential credential) {
- return addInstruction(Instruction.make(Operation.ADD_CREDENTIAL, authority, credential));
- }
-
- /**
- * Adds some credentials to this state.
- *
- * @param authority The authority from which the cookie was received.
- * @param credentials The credentials to be added.
- */
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState addCredentials(AuthnAuthority authority,
- Iterable<Credential> credentials) {
- AuthnSessionState state = this;
- for (Credential credential : credentials) {
- state = state.addCredential(authority, credential);
- }
- return state;
- }
-
- /**
- * Removes a credential from this state.
- *
- * @param authority The authority from which the credential was originally received.
- * @param credential The credential to be removed.
- */
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState removeCredential(AuthnAuthority authority,
- Credential credential) {
- return addInstruction(Instruction.make(Operation.REMOVE_CREDENTIAL, authority, credential));
- }
-
- /**
- * Adds a verification to this state.
- *
- * @param authority The authority that performed the verification process.
- * @param verification The verification to be added.
- */
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState addVerification(AuthnAuthority authority, Verification verification) {
- return addInstruction(Instruction.make(Operation.ADD_VERIFICATION, authority, verification));
- }
-
- /**
- * Adds some verifications to this state.
- *
- * @param authority The authority that performed the verification process.
- * @param verifications The verifications to be added.
- */
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState addVerifications(AuthnAuthority authority,
- Iterable<Verification> verifications) {
- AuthnSessionState state = this;
- for (Verification verification : verifications) {
- state = state.addVerification(authority, verification);
- }
- return state;
- }
-
- /**
- * Removes a verification from this state.
- *
- * @param authority The authority that performed the verification process.
- * @param verification The verification to be removed.
- */
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState removeVerification(AuthnAuthority authority, Verification verification) {
- return addInstruction(Instruction.make(Operation.REMOVE_VERIFICATION, authority, verification));
- }
-
- /**
- * Removes some verifications from this state.
- *
- * @param authority The authority that performed the verification process.
- * @param verifications The verifications to be removed.
- */
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState removeVerifications(AuthnAuthority authority,
- Iterable<Verification> verifications) {
- AuthnSessionState state = this;
- for (Verification verification : verifications) {
- state = state.removeVerification(authority, verification);
- }
- return state;
- }
-
- /**
- * Computes a summary of this state's contents.
- *
- * @param credentialGroups The credential groups associated with this session.
- * @return An immutable summary of the state's contents.
- */
- @CheckReturnValue
- @Nonnull
- public Summary computeSummary(Iterable<CredentialGroup> credentialGroups) {
- return evolveSummary(new Evolver(credentialGroups));
- }
-
- /**
- * Computes a summary by extending a given summary with this state's contents.
- *
- * @param summary The summary to be extended.
- * @return An immutable extended summary.
- */
- @CheckReturnValue
- @Nonnull
- public Summary evolveSummary(Summary summary) {
- return evolveSummary(summary.evolve());
- }
-
- private Summary evolveSummary(Evolver evolver) {
- for (Instruction instruction : getInstructions()) {
- AuthnAuthority authority = instruction.getAuthority();
- Object operand = instruction.getOperand();
- switch (instruction.getOperation()) {
- case ADD_COOKIE:
- evolver.addCookie(authority, (GCookie) operand);
- break;
- case REMOVE_COOKIE:
- evolver.removeCookie(authority, (GCookie) operand);
- break;
- case ADD_CREDENTIAL:
- evolver.addCredential(authority, (Credential) operand);
- break;
- case REMOVE_CREDENTIAL:
- evolver.removeCredential(authority, (Credential) operand);
- break;
- case ADD_VERIFICATION:
- evolver.addVerification(authority, (Verification) operand);
- break;
- case REMOVE_VERIFICATION:
- evolver.removeVerification(authority, (Verification) operand);
- break;
- default:
- throw new IllegalStateException("Unknown instruction operation: "
- + instruction.getOperation());
- }
- }
- return evolver.getSummary();
- }
-
- @NotThreadSafe
- @ParametersAreNonnullByDefault
- private static final class Evolver {
- @Nonnull final ImmutableList<CredentialGroup> credentialGroups;
- @Nonnull final Map<AuthnAuthority, CookieStore> cookiesMap;
- @Nonnull final SetMultimap<AuthnAuthority, Credential> credentialsMap;
- @Nonnull final Map<AuthnAuthority, Verification> verificationsMap;
-
- Evolver(Iterable<CredentialGroup> credentialGroups) {
- this.credentialGroups = ImmutableList.copyOf(credentialGroups);
- cookiesMap = Maps.<AuthnAuthority, CookieStore>newHashMap();
- credentialsMap = HashMultimap.<AuthnAuthority, Credential>create();
- verificationsMap = Maps.<AuthnAuthority, Verification>newHashMap();
- }
-
- Evolver(ImmutableList<CredentialGroup> credentialGroups,
- ImmutableMap<AuthnAuthority, ImmutableSet<GCookie>> cookiesMap,
- ImmutableSetMultimap<AuthnAuthority, Credential> credentialsMap,
- ImmutableMap<AuthnAuthority, Verification> verificationsMap) {
- this.credentialGroups = credentialGroups;
- this.cookiesMap = thawCookiesMap(cookiesMap);
- this.credentialsMap = HashMultimap.create(credentialsMap);
- this.verificationsMap = Maps.newHashMap(verificationsMap);
- }
-
- static Map<AuthnAuthority, CookieStore> thawCookiesMap(
- ImmutableMap<AuthnAuthority, ImmutableSet<GCookie>> cookiesMap) {
- Map<AuthnAuthority, CookieStore> result = Maps.newHashMap();
- for (Map.Entry<AuthnAuthority, ImmutableSet<GCookie>> entry : cookiesMap.entrySet()) {
- CookieStore cookies = GCookie.makeStore();
- cookies.addAll(entry.getValue());
- result.put(entry.getKey(), cookies);
- }
- return result;
- }
-
- Summary getSummary() {
- return new Summary(credentialGroups, freezeCookiesMap(),
- ImmutableSetMultimap.copyOf(credentialsMap), ImmutableMap.copyOf(verificationsMap));
- }
-
- ImmutableMap<AuthnAuthority, ImmutableSet<GCookie>> freezeCookiesMap() {
- ImmutableMap.Builder<AuthnAuthority, ImmutableSet<GCookie>> builder = ImmutableMap.builder();
- for (Map.Entry<AuthnAuthority, CookieStore> entry : cookiesMap.entrySet()) {
- builder.put(entry.getKey(), ImmutableSet.copyOf(entry.getValue()));
- }
- return builder.build();
- }
-
- void addCookie(AuthnAuthority authority, GCookie cookie) {
- getCookies(authority).add(cookie);
- }
-
- void removeCookie(AuthnAuthority authority, GCookie cookie) {
- getCookies(authority).remove(cookie);
- }
-
- CookieStore getCookies(AuthnAuthority authority) {
- CookieStore cookies = cookiesMap.get(authority);
- if (cookies == null) {
- cookies = GCookie.makeStore();
- cookiesMap.put(authority, cookies);
- }
- return cookies;
- }
-
- void addCredential(AuthnAuthority authority, Credential credential) {
- AuthnAuthority cgAuthority = getCredGroupAuthority(authority);
- if (!credentialsMap.containsEntry(cgAuthority, credential)) {
- Iterable<Credential> removed
- = SecurityManagerUtil.removeInPlace(credentialsMap.get(cgAuthority),
- AbstractCredential.getTypePredicate(credential.getClass()));
- for (AuthnAuthority mechAuthority : getMechAuthorities(cgAuthority)) {
- Verification verification = verificationsMap.get(mechAuthority);
- if (verification != null && verification.containsAnyCredential(removed)) {
- verificationsMap.remove(mechAuthority);
- }
- }
- credentialsMap.put(cgAuthority, credential);
- }
- }
-
- void removeCredential(AuthnAuthority authority, Credential credential) {
- AuthnAuthority cgAuthority = getCredGroupAuthority(authority);
- if (credentialsMap.containsEntry(cgAuthority, credential)) {
- for (AuthnAuthority mechAuthority : getMechAuthorities(cgAuthority)) {
- Verification verification = verificationsMap.get(mechAuthority);
- if (verification != null && verification.containsCredential(credential)) {
- verificationsMap.remove(mechAuthority);
- }
- }
- credentialsMap.remove(cgAuthority, credential);
- }
- }
-
- void addVerification(AuthnAuthority authority, Verification verification) {
- verificationsMap.put(authority, verification);
- for (Credential credential : verification.getCredentials()) {
- addCredential(authority, credential);
- }
- }
-
- void removeVerification(AuthnAuthority authority, Verification verification) {
- if (verification.equals(verificationsMap.get(authority))) {
- verificationsMap.remove(authority);
- }
- }
-
- AuthnAuthority getCredGroupAuthority(AuthnAuthority authority) {
- for (CredentialGroup credentialGroup : credentialGroups) {
- for (AuthnMechanism mechanism : credentialGroup.getMechanisms()) {
- if (authority.equals(mechanism.getAuthority())) {
- return credentialGroup.getAuthority();
- }
- }
- }
- return authority;
- }
-
- Iterable<AuthnAuthority> getMechAuthorities(AuthnAuthority authority) {
- for (CredentialGroup credentialGroup : credentialGroups) {
- if (authority.equals(credentialGroup.getAuthority())) {
- return Iterables.transform(credentialGroup.getMechanisms(),
- AuthnMechanism.getAuthorityFunction());
- }
- }
- return ImmutableList.of(authority);
- }
- }
-
- /**
- * The result of {@link #computeSummary}, this structure contains a summary of
- * the session state as computed by executing the session-state's
- * instructions.
- */
- @Immutable
- @ParametersAreNonnullByDefault
- public static final class Summary {
- @Nonnull private final ImmutableList<CredentialGroup> credentialGroups;
- @Nonnull private final ImmutableMap<AuthnAuthority, ImmutableSet<GCookie>> cookiesMap;
- @Nonnull private final ImmutableSetMultimap<AuthnAuthority, Credential> credentialsMap;
- @Nonnull private final ImmutableMap<AuthnAuthority, Verification> verificationsMap;
-
- private Summary(ImmutableList<CredentialGroup> credentialGroups,
- ImmutableMap<AuthnAuthority, ImmutableSet<GCookie>> cookiesMap,
- ImmutableSetMultimap<AuthnAuthority, Credential> credentialsMap,
- ImmutableMap<AuthnAuthority, Verification> verificationsMap) {
- this.credentialGroups = credentialGroups;
- this.cookiesMap = cookiesMap;
- this.credentialsMap = credentialsMap;
- this.verificationsMap = verificationsMap;
- }
-
- @CheckReturnValue
- @Nonnull
- private Evolver evolve() {
- return new Evolver(credentialGroups, cookiesMap, credentialsMap, verificationsMap);
- }
-
- /**
- * Gets the credential groups that were used to generate this summary.
- */
- @CheckReturnValue
- @Nonnull
- public ImmutableList<CredentialGroup> getCredentialGroups() {
- return credentialGroups;
- }
-
- /**
- * Gets all the cookies in this summary.
- *
- * @return An immutable map of the cookies for each authority.
- */
- @CheckReturnValue
- @Nonnull
- public ImmutableMap<AuthnAuthority, ImmutableSet<GCookie>> getCookiesMap() {
- return cookiesMap;
- }
-
- /**
- * Gets all the credentials in this summary.
- *
- * @return An immutable map of the credentials for each authority.
- */
- public ImmutableSetMultimap<AuthnAuthority, Credential> getCredentialsMap() {
- return credentialsMap;
- }
-
- /**
- * Gets all the verifications in this summary.
- *
- * @return An immutable map of the verifications for each authority.
- */
- @CheckReturnValue
- @Nonnull
- public ImmutableMap<AuthnAuthority, Verification> getVerificationsMap() {
- return verificationsMap;
- }
-
- /**
- * Gets the cookies in this summary for some specified authorities.
- *
- * @param predicate A predicate specifying the authorities to get cookies for.
- * @return An immutable set of the cookies for the matching authorities.
- */
- @CheckReturnValue
- @Nonnull
- public ImmutableSet<GCookie> getCookies(Predicate<AuthnAuthority> predicate) {
- ImmutableSet.Builder<GCookie> builder = ImmutableSet.builder();
- for (Map.Entry<AuthnAuthority, ImmutableSet<GCookie>> entry : cookiesMap.entrySet()) {
- if (predicate.apply(entry.getKey())) {
- builder.addAll(entry.getValue());
- }
- }
- return builder.build();
- }
-
- /**
- * Gets the unexpired cookies in this summary for some specified authorities.
- *
- * @param predicate A predicate specifying the authorities to get cookies for.
- * @param timeStamp A reference time to use for expiring cookies.
- * @return An immutable set of the unexpired cookies for the matching authorities.
- */
- @CheckReturnValue
- @Nonnull
- public ImmutableSet<GCookie> getCookies(Predicate<AuthnAuthority> predicate, long timeStamp) {
- ImmutableSet.Builder<GCookie> builder = ImmutableSet.builder();
- for (Map.Entry<AuthnAuthority, ImmutableSet<GCookie>> entry : cookiesMap.entrySet()) {
- if (predicate.apply(entry.getKey())) {
- for (GCookie cookie : entry.getValue()) {
- if (!cookie.isExpired(timeStamp)) {
- builder.add(cookie);
- }
- }
- }
- }
- return builder.build();
- }
-
- /**
- * Gets the credentials in this summary for some specified authorities.
- *
- * @param predicate A predicate specifying the authorities to get credentials for.
- * @return An immutable set of the credentials for the matching authorities.
- */
- @CheckReturnValue
- @Nonnull
- public ImmutableSet<Credential> getCredentials(Predicate<AuthnAuthority> predicate) {
- ImmutableSet.Builder<Credential> builder = ImmutableSet.builder();
- for (AuthnAuthority authority : credentialsMap.keySet()) {
- if (predicate.apply(authority)) {
- builder.addAll(credentialsMap.get(authority));
- }
- }
- return builder.build();
- }
-
- /**
- * Gets the verifications in this summary for some specified authorities.
- *
- * @param predicate A predicate specifying the authorities to get verifications for.
- * @return An immutable set of the verifications for the matching authorities.
- */
- @CheckReturnValue
- @Nonnull
- public ImmutableSet<Verification> getVerifications(Predicate<AuthnAuthority> predicate) {
- ImmutableSet.Builder<Verification> builder = ImmutableSet.builder();
- for (Map.Entry<AuthnAuthority, Verification> entry : verificationsMap.entrySet()) {
- if (predicate.apply(entry.getKey())) {
- builder.add(entry.getValue());
- }
- }
- return builder.build();
- }
-
- /**
- * Gets the unexpired verifications in this summary for some specified authorities.
- *
- * @param predicate A predicate specifying the authorities to get verifications for.
- * @param timeStamp A reference time to use for expiring verifications.
- * @return An immutable set of the unexpired verifications for the matching authorities.
- */
- @CheckReturnValue
- @Nonnull
- public ImmutableSet<Verification> getVerifications(Predicate<AuthnAuthority> predicate,
- long timeStamp) {
- ImmutableSet.Builder<Verification> builder = ImmutableSet.builder();
- for (Map.Entry<AuthnAuthority, Verification> entry : verificationsMap.entrySet()) {
- if (predicate.apply(entry.getKey())) {
- Verification verification = entry.getValue();
- if (!verification.hasExpired(timeStamp)) {
- builder.add(verification);
- }
- }
- }
- return builder.build();
- }
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(AuthnSessionState.class,
- ProxyTypeAdapter.make(AuthnSessionState.class, LocalProxy.class));
- builder.registerTypeAdapter(Instruction.class,
- new Instruction.LocalTypeAdapter());
- }
-
- private static final class LocalProxy implements TypeProxy<AuthnSessionState> {
- List<Instruction> instructions;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(AuthnSessionState state) {
- instructions = state.getInstructions();
- }
-
- @Override
- public AuthnSessionState build() {
- return AuthnSessionState.of(instructions);
- }
- }
-
- /**
- * An instruction, consisting of an operation, an authority, and an operand.
- */
- @Immutable
- @ParametersAreNonnullByDefault
- public static final class Instruction {
- @Nonnull private final Operation operation;
- @Nonnull private final AuthnAuthority authority;
- @Nonnull private final Object operand;
-
- private Instruction(Operation operation, AuthnAuthority authority, Object operand) {
- this.operation = operation;
- this.authority = authority;
- this.operand = operand;
- }
-
- @CheckReturnValue
- @Nonnull
- public static Instruction make(Operation operation, AuthnAuthority authority, Object operand) {
- Preconditions.checkNotNull(authority);
- Preconditions.checkArgument(operation.getOperandClass().isInstance(operand));
- return new Instruction(operation, authority, operand);
- }
-
- @CheckReturnValue
- @Nonnull
- public Operation getOperation() {
- return operation;
- }
-
- @CheckReturnValue
- @Nonnull
- public AuthnAuthority getAuthority() {
- return authority;
- }
-
- @CheckReturnValue
- @Nonnull
- public Object getOperand() {
- return operand;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof Instruction)) { return false; }
- Instruction other = (Instruction) object;
- return Objects.equal(getOperation(), other.getOperation())
- && Objects.equal(getAuthority(), other.getAuthority())
- && Objects.equal(getOperand(), other.getOperand());
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(getOperation(), getAuthority(), getOperand());
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- switch (operation) {
- case ADD_COOKIE:
- case ADD_CREDENTIAL:
- case ADD_VERIFICATION:
- builder.append("add to ");
- break;
- case REMOVE_COOKIE:
- case REMOVE_CREDENTIAL:
- case REMOVE_VERIFICATION:
- builder.append("remove from ");
- break;
- default:
- throw new IllegalStateException("Unknown operation: " + operation);
- }
- builder.append(authority);
- builder.append(": ");
- builder.append(operand);
- return builder.toString();
- }
-
- private static final class LocalTypeAdapter
- implements JsonSerializer<Instruction>, JsonDeserializer<Instruction> {
- static final String KEY_OPERATION = "operation";
- static final String KEY_AUTHORITY = "authority";
- static final String KEY_OPERAND = "operand";
-
- LocalTypeAdapter() {
- }
-
- @Override
- public JsonElement serialize(Instruction instruction, Type type,
- JsonSerializationContext context) {
- JsonObject jo = new JsonObject();
- Operation operation = instruction.getOperation();
- jo.addProperty(KEY_OPERATION, operation.toString());
- jo.add(KEY_AUTHORITY, context.serialize(instruction.getAuthority(), AuthnAuthority.class));
- jo.add(KEY_OPERAND,
- context.serialize(instruction.getOperand(), operation.getOperandClass()));
- return jo;
- }
-
- @Override
- public Instruction deserialize(JsonElement src, Type type,
- JsonDeserializationContext context) {
- JsonObject jo = src.getAsJsonObject();
- Operation operation = Operation.valueOf(jo.getAsJsonPrimitive(KEY_OPERATION).getAsString());
- AuthnAuthority authority = context.deserialize(jo.get(KEY_AUTHORITY), AuthnAuthority.class);
- return Instruction.make(operation, authority,
- context.deserialize(jo.get(KEY_OPERAND), operation.getOperandClass()));
- }
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/authncontroller/ExportedState.java b/src/com/google/enterprise/secmgr/authncontroller/ExportedState.java
index aa8e748..203bbbe 100644
--- a/src/com/google/enterprise/secmgr/authncontroller/ExportedState.java
+++ b/src/com/google/enterprise/secmgr/authncontroller/ExportedState.java
@@ -18,14 +18,7 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
-import com.google.enterprise.secmgr.common.GCookie;
-import com.google.enterprise.secmgr.config.AuthnMechBasic;
-import com.google.enterprise.secmgr.config.AuthnMechConnector;
-import com.google.enterprise.secmgr.config.AuthnMechLdap;
-import com.google.enterprise.secmgr.config.AuthnMechNtlm;
-import com.google.enterprise.secmgr.config.AuthnMechanism;
import com.google.enterprise.secmgr.config.ConfigSingleton;
-import com.google.enterprise.secmgr.http.ConnectorUtil;
import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
import com.google.enterprise.secmgr.json.TypeAdapters;
import com.google.enterprise.secmgr.json.TypeProxy;
@@ -191,78 +184,18 @@
@Nonnegative private final int version;
@Nonnegative private final long timeStamp;
- @Nonnull private final AuthnSessionState sessionState;
@Nonnull private final Credentials pviCredentials;
@Nonnull private final Credentials basicCredentials;
@Nonnull private final ImmutableMap<String, Credentials> connectorCredentials;
- @Nonnull private final ImmutableSet<GCookie> cookies;
private ExportedState(@Nonnegative int version, @Nonnegative long timeStamp,
- AuthnSessionState sessionState, Credentials pviCredentials, Credentials basicCredentials,
- ImmutableMap<String, Credentials> connectorCredentials, ImmutableSet<GCookie> cookies) {
+ Credentials pviCredentials, Credentials basicCredentials,
+ ImmutableMap<String, Credentials> connectorCredentials) {
this.version = version;
this.timeStamp = timeStamp;
- this.sessionState = sessionState;
this.pviCredentials = pviCredentials;
this.basicCredentials = basicCredentials;
this.connectorCredentials = connectorCredentials;
- this.cookies = cookies;
- }
-
- /**
- * Makes an exported-state object from a given session snapshot.
- *
- * @param snapshot A snapshot to derive the exported state from.
- * @return A corresponding exported-state object.
- */
- @CheckReturnValue
- @Nonnull
- public static ExportedState make(SessionSnapshot snapshot) {
- long timeStamp = snapshot.getTimeStamp();
- Credentials pviCredentials
- = credentialsForView(snapshot.getPrimaryVerifiedView(), Credentials.EMPTY);
- Credentials basicCredentials = credentialsForView(getBasicView(snapshot), pviCredentials);
- ImmutableMap.Builder<String, Credentials> connectorCredentialsBuilder = ImmutableMap.builder();
- for (String instanceName : ConnectorUtil.getUrlMap().keySet()) {
- connectorCredentialsBuilder.put(instanceName,
- credentialsForView(findConnectorView(instanceName, snapshot), pviCredentials));
- }
- ImmutableMap<String, Credentials> connectorCredentials = connectorCredentialsBuilder.build();
- ImmutableSet<GCookie> cookies = ImmutableSet.copyOf(snapshot.getView().getAuthorityCookies());
- return new ExportedState(CURRENT_VERSION, timeStamp, snapshot.getState(), pviCredentials,
- basicCredentials, connectorCredentials, cookies);
- }
-
- private static Credentials credentialsForView(SessionView view, Credentials fallback) {
- if (view == null) {
- return fallback;
- }
- if (view.hasVerifiedPrincipalAndPassword()) {
- return Credentials.make(view.getUsername(), view.getDomain(), view.getPassword(),
- view.getGroups());
- }
- return Credentials.EMPTY;
- }
-
- private static SessionView getBasicView(SessionSnapshot snapshot) {
- for (AuthnMechanism mechanism : snapshot.getConfig().getMechanisms()) {
- if (mechanism instanceof AuthnMechBasic
- || mechanism instanceof AuthnMechLdap
- || mechanism instanceof AuthnMechNtlm) {
- return snapshot.getView(mechanism);
- }
- }
- return null;
- }
-
- private static SessionView findConnectorView(String instanceName, SessionSnapshot snapshot) {
- for (AuthnMechanism mechanism : snapshot.getConfig().getMechanisms()) {
- if (mechanism instanceof AuthnMechConnector
- && instanceName.equals(((AuthnMechConnector) mechanism).getConnectorName())) {
- return snapshot.getView(mechanism);
- }
- }
- return null;
}
/**
@@ -275,16 +208,6 @@
}
/**
- * Gets the security manager's session state, consisting of all cookies,
- * credentials, and verifications generated during authentication.
- */
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState getSessionState() {
- return sessionState;
- }
-
- /**
* Gets the credentials for the Primary Verified Identity (PVI).
*/
@CheckReturnValue
@@ -314,15 +237,6 @@
}
/**
- * Gets all the cookies collected by the security manager.
- */
- @CheckReturnValue
- @Nonnull
- public ImmutableSet<GCookie> getCookies() {
- return cookies;
- }
-
- /**
* Gets a JSON string representation for this object.
*/
@CheckReturnValue
@@ -340,15 +254,13 @@
return ConfigSingleton.getGson().fromJson(jsonString, ExportedState.class);
}
- static void registerTypeAdapters(GsonBuilder builder) {
+ public static void registerTypeAdapters(GsonBuilder builder) {
builder.registerTypeAdapter(Credentials.class,
ProxyTypeAdapter.make(Credentials.class, Credentials.LocalProxy.class));
builder.registerTypeAdapter(ExportedState.class,
ProxyTypeAdapter.make(ExportedState.class, LocalProxy.class));
builder.registerTypeAdapter(new TypeToken<ImmutableSet<String>>() {}.getType(),
TypeAdapters.immutableSet());
- builder.registerTypeAdapter(new TypeToken<ImmutableSet<GCookie>>() {}.getType(),
- TypeAdapters.immutableSet());
builder.registerTypeAdapter(new TypeToken<ImmutableMap<String, Credentials>>() {}.getType(),
TypeAdapters.immutableMap());
}
@@ -356,11 +268,9 @@
private static final class LocalProxy implements TypeProxy<ExportedState> {
int version;
long timeStamp;
- AuthnSessionState sessionState;
Credentials pviCredentials;
Credentials basicCredentials;
ImmutableMap<String, Credentials> connectorCredentials;
- ImmutableSet<GCookie> cookies;
@SuppressWarnings("unused")
LocalProxy() {
@@ -370,20 +280,17 @@
LocalProxy(ExportedState state) {
version = state.version;
timeStamp = state.timeStamp;
- sessionState = state.getSessionState();
pviCredentials = state.getPviCredentials();
basicCredentials = state.getBasicCredentials();
connectorCredentials = state.getConnectorCredentials();
- cookies = state.getCookies();
}
@Override
public ExportedState build() {
Preconditions.checkArgument(version >= MIN_VERSION && version <= MAX_VERSION);
Preconditions.checkArgument(timeStamp >= 0);
- Preconditions.checkArgument(sessionState != null);
- return new ExportedState(version, timeStamp, sessionState, pviCredentials, basicCredentials,
- ImmutableMap.copyOf(connectorCredentials), ImmutableSet.copyOf(cookies));
+ return new ExportedState(version, timeStamp, pviCredentials, basicCredentials,
+ ImmutableMap.copyOf(connectorCredentials));
}
}
}
diff --git a/src/com/google/enterprise/secmgr/authncontroller/SessionSnapshot.java b/src/com/google/enterprise/secmgr/authncontroller/SessionSnapshot.java
deleted file mode 100644
index c18e187..0000000
--- a/src/com/google/enterprise/secmgr/authncontroller/SessionSnapshot.java
+++ /dev/null
@@ -1,234 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.google.enterprise.secmgr.authncontroller;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Maps;
-import com.google.enterprise.secmgr.common.GCookie;
-import com.google.enterprise.secmgr.common.SecurityManagerUtil;
-import com.google.enterprise.secmgr.common.SessionUtil;
-import com.google.enterprise.secmgr.config.AuthnMechanism;
-import com.google.enterprise.secmgr.config.CredentialGroup;
-import com.google.enterprise.secmgr.config.SecurityManagerConfig;
-import com.google.enterprise.secmgr.identity.Verification;
-
-import org.joda.time.DateTimeUtils;
-import org.joda.time.format.ISODateTimeFormat;
-
-import java.net.URL;
-import java.util.Map;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnegative;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * An immutable snapshot of the session's state.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class SessionSnapshot {
- @Nonnull private final String sessionId;
- @Nonnull private final SecurityManagerConfig config;
- @Nullable private final URL authnEntryUrl;
- @Nonnull private final ImmutableCollection<GCookie> userAgentCookies;
- @Nonnull private final AuthnSessionState state;
- @Nonnegative private final long timeStamp;
- @Nonnull private final SessionView unspecializedView;
- @GuardedBy("itself")
- @Nonnull private final Map<AuthnMechanism, SessionView> savedMechanismViews;
- @GuardedBy("itself")
- @Nonnull private final Map<CredentialGroup, SessionView> savedCredentialGroupViews;
-
- private SessionSnapshot(String sessionId, SecurityManagerConfig config,
- @Nullable URL authnEntryUrl, ImmutableCollection<GCookie> userAgentCookies,
- AuthnSessionState state, @Nonnegative long timeStamp) {
- this.sessionId = sessionId;
- this.config = config;
- this.authnEntryUrl = authnEntryUrl;
- this.userAgentCookies = userAgentCookies;
- this.state = state;
- this.timeStamp = timeStamp;
- unspecializedView = SessionView.create(this);
- savedMechanismViews = Maps.newHashMap();
- savedCredentialGroupViews = Maps.newHashMap();
- }
-
- static SessionSnapshot make(String sessionId, SecurityManagerConfig config,
- @Nullable URL authnEntryUrl, ImmutableCollection<GCookie> userAgentCookies,
- AuthnSessionState state) {
- return new SessionSnapshot(sessionId, config, authnEntryUrl, userAgentCookies,
- state, DateTimeUtils.currentTimeMillis());
- }
-
- @VisibleForTesting
- public static SessionSnapshot make(SecurityManagerConfig config, AuthnSessionState state) {
- return make(SessionUtil.generateId(), config, null, ImmutableList.<GCookie>of(), state);
- }
-
- SessionSnapshot withNewUserAgentCookies(ImmutableCollection<GCookie> userAgentCookies) {
- return new SessionSnapshot(sessionId, config, authnEntryUrl, userAgentCookies,
- state, timeStamp);
- }
-
- @CheckReturnValue
- @Nonnull
- public String getSessionId() {
- return sessionId;
- }
-
- @CheckReturnValue
- @Nonnull
- public SecurityManagerConfig getConfig() {
- return config;
- }
-
- @CheckReturnValue
- @Nullable
- URL getAuthnEntryUrl() {
- return authnEntryUrl;
- }
-
- @CheckReturnValue
- @Nonnull
- ImmutableCollection<GCookie> getUserAgentCookies() {
- return userAgentCookies;
- }
-
- @CheckReturnValue
- @Nonnull
- public AuthnSessionState getState() {
- return state;
- }
-
- @CheckReturnValue
- @Nonnegative
- long getTimeStamp() {
- return timeStamp;
- }
-
- /**
- * Gets a view of this snapshot specialized for a given authentication
- * mechanism.
- *
- * @param mechanism An authentication mechanism.
- * @return A mechanism view of this snapshot.
- */
- @CheckReturnValue
- @Nonnull
- public SessionView getView(AuthnMechanism mechanism) {
- synchronized (savedMechanismViews) {
- SessionView view = savedMechanismViews.get(mechanism);
- if (view == null) {
- view = SessionView.create(this, mechanism);
- savedMechanismViews.put(mechanism, view);
- }
- return view;
- }
- }
-
- /**
- * Gets a view of this snapshot specialized for a given credential group.
- *
- * @param credentialGroup A credential group.
- * @return A credential-group view of this snapshot.
- */
- @CheckReturnValue
- @Nonnull
- public SessionView getView(CredentialGroup credentialGroup) {
- synchronized (savedCredentialGroupViews) {
- SessionView view = savedCredentialGroupViews.get(credentialGroup);
- if (view == null) {
- view = SessionView.create(this, credentialGroup);
- savedCredentialGroupViews.put(credentialGroup, view);
- }
- return view;
- }
- }
-
- /**
- * Gets an unspecialized view of this snapshot.
- *
- * @return An unspecialized view of this snapshot.
- */
- @CheckReturnValue
- @Nonnull
- public SessionView getView() {
- return unspecializedView;
- }
-
- /**
- * Gets the expiration time for this snapshot.
- *
- * @return The expiration time.
- */
- @CheckReturnValue
- public long getExpirationTime() {
- SessionView view = getView();
- return view.isSatisfied()
- ? Verification.minimumExpirationTime(view.getVerifications())
- : timeStamp;
- }
-
- /**
- * Get a "primary verified view". This is a view containing a principal
- * that's been verified, with preference given to the default credential
- * group's view, if possible.
- *
- * <p>The primary verified view is intended for use by the GSA, and this
- * method is only called when generating output for the GSA. It should
- * <b>never</b> be used for any other purpose.
- *
- * @return The primary verified view, or null if there isn't one.
- */
- public SessionView getPrimaryVerifiedView() {
- SessionView winner = null;
- for (CredentialGroup credentialGroup : getConfig().getCredentialGroups()) {
- SessionView view = getView(credentialGroup);
- if (view.hasVerifiedPrincipal()) {
- if (credentialGroup.isDefault()) {
- return view;
- }
- if (winner == null) {
- winner = view;
- }
- }
- }
- return winner;
- }
-
- @CheckReturnValue
- @Nonnull
- public String logMessage(String format, Object... args) {
- return SecurityManagerUtil.sessionLogMessage(sessionId, String.format(format, args));
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("{SessionSnapshot taken at ");
- builder.append(ISODateTimeFormat.dateTime().print(timeStamp));
- builder.append(" of session ");
- builder.append(sessionId);
- builder.append("}");
- return builder.toString();
- }
-}
diff --git a/src/com/google/enterprise/secmgr/authncontroller/SessionView.java b/src/com/google/enterprise/secmgr/authncontroller/SessionView.java
deleted file mode 100644
index 1fd6157..0000000
--- a/src/com/google/enterprise/secmgr/authncontroller/SessionView.java
+++ /dev/null
@@ -1,643 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.google.enterprise.secmgr.authncontroller;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.enterprise.secmgr.common.GCookie;
-import com.google.enterprise.secmgr.config.AuthnAuthority;
-import com.google.enterprise.secmgr.config.AuthnMechanism;
-import com.google.enterprise.secmgr.config.CredentialGroup;
-import com.google.enterprise.secmgr.identity.AuthnPrincipal;
-import com.google.enterprise.secmgr.identity.CredPassword;
-import com.google.enterprise.secmgr.identity.Credential;
-import com.google.enterprise.secmgr.identity.GroupMemberships;
-import com.google.enterprise.secmgr.identity.Verification;
-import com.google.enterprise.secmgr.identity.VerificationStatus;
-
-import java.net.URL;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnegative;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A view of a session snapshot that may be specialized or unspecialized.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public abstract class SessionView {
-
- @Nonnull protected final SessionSnapshot snapshot;
- @GuardedBy("this") @Nonnull protected AuthnSessionState.Summary summary;
-
- protected SessionView(SessionSnapshot snapshot) {
- Preconditions.checkNotNull(snapshot);
- this.snapshot = snapshot;
- summary = null;
- }
-
- /**
- * Creates a session view specialized for a given authentication mechanism.
- *
- * @param snapshot The session snapshot the view is a specialization of.
- * @param mechanism The authentication mechanism to specialize for.
- * @return A view of the snapshot specialized for the mechanism.
- */
- @CheckReturnValue
- @Nonnull
- static SessionView create(SessionSnapshot snapshot, AuthnMechanism mechanism) {
- return new SessionViewForMechanism(snapshot, mechanism);
- }
-
- /**
- * Creates a session view specialized for a given credential group.
- *
- * @param snapshot The session snapshot the view is a specialization of.
- * @param credentialGroup The credential group to specialize for.
- * @return A view of the snapshot specialized for the credential group.
- */
- @CheckReturnValue
- @Nonnull
- static SessionView create(SessionSnapshot snapshot, CredentialGroup credentialGroup) {
- return new SessionViewForCredentialGroup(snapshot, credentialGroup);
- }
-
- /**
- * Creates an unspecialized session view.
- *
- * @param snapshot The session snapshot the view is a specialization of.
- * @return An unspecialized view of the snapshot.
- */
- @CheckReturnValue
- @Nonnull
- static SessionView create(SessionSnapshot snapshot) {
- return new SessionViewUnspecialized(snapshot);
- }
-
- /**
- * Gets a new view identical to this one except that it contains the given
- * user-agent cookies. Used to update a view after returning from a
- * credentials gatherer.
- *
- * @param userAgentCookies The new user-agent cookies.
- * @return A new view as specified.
- */
- @CheckReturnValue
- @Nonnull
- SessionView withNewUserAgentCookies(ImmutableCollection<GCookie> userAgentCookies) {
- return withNewSnapshot(snapshot.withNewUserAgentCookies(userAgentCookies));
- }
-
- @CheckReturnValue
- @Nonnull
- protected abstract SessionView withNewSnapshot(SessionSnapshot snapshot);
-
- /**
- * Is this a mechanism view?
- *
- * @return True only if this view is specialized for an authentication mechanism.
- */
- @CheckReturnValue
- public boolean isSpecializedForMechanism() {
- return false;
- }
-
- /**
- * Is this a credential-group view?
- *
- * @return True only if this view is specialized for a credential group.
- */
- @CheckReturnValue
- public boolean isSpecializedForCredentialGroup() {
- return false;
- }
-
- /**
- * Is this an unspecialized view?
- *
- * @return True only if this is an unspecialized view.
- */
- @CheckReturnValue
- public boolean isUnspecialized() {
- return false;
- }
-
- /**
- * Gets a summary of the view's session state.
- */
- @CheckReturnValue
- @Nonnull
- public synchronized AuthnSessionState.Summary getSummary() {
- if (summary == null) {
- summary = snapshot.getState().computeSummary(snapshot.getConfig().getCredentialGroups());
- }
- return summary;
- }
-
- /**
- * Gets the session ID string.
- *
- * @return The session ID string.
- */
- @CheckReturnValue
- @Nonnull
- public String getSessionId() {
- return snapshot.getSessionId();
- }
-
- /**
- * Gets the URL that initiated the current authentication request.
- *
- * @return The authentication request URL, or null if we're not processing an
- * authentication request.
- */
- @CheckReturnValue
- @Nullable
- public URL getAuthnEntryUrl() {
- return snapshot.getAuthnEntryUrl();
- }
-
- /**
- * Gets the URL that initiated the current authentication request.
- *
- * @return The authentication request URL as a string, or null if we're not
- * processing an authentication request.
- */
- @CheckReturnValue
- @Nullable
- public String getAuthnEntryUrlString() {
- return getAuthnEntryUrl().toString();
- }
-
- /**
- * Gets the time at which this view's snapshot was taken.
- *
- * @return The snapshot time in milliseconds since the epoch.
- */
- @CheckReturnValue
- @Nonnegative
- public long getTimeStamp() {
- return snapshot.getTimeStamp();
- }
-
- /**
- * Gets this view's authority, if it is a specialized view.
- *
- * @return The authority.
- * @throws UnsupportedOperationException if this is not a specialized view.
- */
- @CheckReturnValue
- @Nonnull
- public abstract AuthnAuthority getAuthority();
-
- /**
- * Gets this view's credential group, if this is a specialized view.
- *
- * @return The credential group.
- * @throws UnsupportedOperationException if this is not a specialized view.
- */
- @CheckReturnValue
- @Nonnull
- public abstract CredentialGroup getCredentialGroup();
-
- /**
- * Gets this view's mechanism, if this is a mechanism view.
- *
- * @return The mechanism associated with this view.
- * @throws UnsupportedOperationException if this is not a mechanism view.
- */
- @CheckReturnValue
- @Nonnull
- public abstract AuthnMechanism getMechanism();
-
- /**
- * Is this view's credential group required to have a principal?
- *
- * @return True if a principal is required.
- * @throws UnsupportedOperationException if this is not a specialized view.
- */
- @CheckReturnValue
- public boolean getRequiresPrincipal() {
- return getCredentialGroup().getRequiresUsername();
- }
-
- /**
- * Gets the configured expiration time.
- *
- * @return The expiration time.
- * @throws UnsupportedOperationException if this is not a mechanism view.
- */
- @CheckReturnValue
- public long getConfiguredExpirationTime() {
- long trustDuration = getMechanism().getTrustDuration();
- return (trustDuration > 0)
- ? snapshot.getTimeStamp() + trustDuration
- : Verification.EXPIRES_AFTER_REQUEST;
- }
-
- protected abstract Predicate<AuthnAuthority> getCookieFilter();
- protected abstract Predicate<AuthnAuthority> getCredentialFilter();
-
- /**
- * Is this view satisfied?
- */
- @CheckReturnValue
- public abstract boolean isSatisfied();
-
- // **************** Cookies ****************
-
- /**
- * Gets the cookies that were received from the user agent in the most recent
- * HTTP request.
- *
- * @return The cookies.
- */
- @CheckReturnValue
- @Nonnull
- public Iterable<GCookie> getUserAgentCookies() {
- return snapshot.getUserAgentCookies();
- }
-
- /**
- * Gets a user-agent cookie by name. Note that there can be multiple such
- * cookies; in that case one is chosen arbitrarily.
- *
- * @param name The name of the cookie to get.
- * @return A cookie with that name, or {@code null} if none.
- */
- @CheckReturnValue
- @Nullable
- public GCookie getUserAgentCookie(String name) {
- Preconditions.checkNotNull(name);
- for (GCookie cookie : getUserAgentCookies()) {
- if (name.equals(cookie.getName())) {
- return cookie;
- }
- }
- return null;
- }
-
- /**
- * Gets the cookies that have been received from this view's authorities.
- *
- * @return An immutable set of the authority cookies.
- */
- @CheckReturnValue
- @Nonnull
- public ImmutableSet<GCookie> getAuthorityCookies() {
- return getSummary().getCookies(getCookieFilter(), getTimeStamp());
- }
-
- // **************** Credentials ****************
-
- /**
- * Gets the credentials that have been gathered for this view.
- *
- * @return An immutable set of the credentials.
- */
- public ImmutableSet<Credential> getCredentials() {
- return getSummary().getCredentials(getCredentialFilter());
- }
-
- /**
- * Gets this view's principal.
- *
- * @return The principal, or {@code null} if there isn't one.
- */
- @CheckReturnValue
- @Nullable
- public AuthnPrincipal getPrincipal() {
- return getUniqueCredential(AuthnPrincipal.class);
- }
-
- /**
- * Gets this view's password credential.
- *
- * @return The password credential, or {@code null} if there isn't one.
- */
- @CheckReturnValue
- @Nullable
- public CredPassword getPasswordCredential() {
- return getUniqueCredential(CredPassword.class);
- }
-
- /**
- * Gets this view's group-memberships credential.
- *
- * @return The group-memberships credential, or {@code null} if there isn't one.
- */
- @CheckReturnValue
- @Nullable
- public GroupMemberships getGroupMemberships() {
- return getUniqueCredential(GroupMemberships.class);
- }
-
- private <T extends Credential> T getUniqueCredential(Class<T> clazz) {
- Credential uniqueCredential = null;
- for (Credential credential : getCredentials()) {
- if (clazz.isInstance(credential)) {
- if (uniqueCredential == null) {
- uniqueCredential = credential;
- } else if (!uniqueCredential.equals(credential)) {
- return null;
- }
- }
- }
- return clazz.cast(uniqueCredential);
- }
-
- /**
- * Does this view have a principal and a password?
- *
- * @return True if the view has exactly one principal and one password.
- */
- @CheckReturnValue
- public boolean hasPrincipalAndPassword() {
- return hasPrincipalAndPassword(getPrincipal(), getPasswordCredential());
- }
-
- private boolean hasPrincipalAndPassword(AuthnPrincipal principal, CredPassword password) {
- return principal != null
- && !principal.getName().isEmpty()
- && password != null
- && !password.getText().isEmpty();
- }
-
- /**
- * Gets this view's principal and password.
- *
- * @return An immutable collection containing those credentials.
- * @throws IllegalStateException unless both are available.
- */
- @CheckReturnValue
- @Nonnull
- public ImmutableCollection<Credential> getPrincipalAndPassword() {
- AuthnPrincipal principal = getPrincipal();
- CredPassword password = getPasswordCredential();
- Preconditions.checkState(hasPrincipalAndPassword(principal, password));
- return ImmutableList.<Credential>of(principal, password);
- }
-
- /**
- * Gets this view's username.
- *
- * @return The username, or {@code null} if there isn't one.
- */
- @CheckReturnValue
- @Nullable
- public String getUsername() {
- AuthnPrincipal principal = getPrincipal();
- return (principal != null) ? principal.getName() : null;
- }
-
- /**
- * Gets this view's domain.
- *
- * @return The domain, or {@code null} if there isn't one.
- */
- @CheckReturnValue
- @Nullable
- public String getDomain() {
- AuthnPrincipal principal = getPrincipal();
- return (principal != null) ? principal.getActiveDirectoryDomain() : null;
- }
-
- /**
- * Gets this view's password.
- *
- * @return The password, or {@code null} if there isn't one.
- */
- @CheckReturnValue
- @Nullable
- public String getPassword() {
- CredPassword password = getPasswordCredential();
- return (password != null) ? password.getText() : null;
- }
-
- /**
- * Gets this view's groups.
- *
- * @return The groups, as an immutable set.
- */
- @CheckReturnValue
- @Nullable
- public ImmutableSet<String> getGroups() {
- GroupMemberships groups = getGroupMemberships();
- return (groups != null) ? groups.getGroups() : ImmutableSet.<String>of();
- }
-
- // **************** Verifications ****************
-
- /**
- * Gets the verifications for this view.
- *
- * @return An immutable set of this view's verifications.
- */
- @CheckReturnValue
- @Nonnull
- public ImmutableSet<Verification> getVerifications() {
- return getSummary().getVerifications(getCredentialFilter(), getTimeStamp());
- }
-
- /**
- * Does this view have a verified principal?
- *
- * @return True if this view has at least one verification containing a
- * principal, and if no other verification contains a different principal.
- */
- @CheckReturnValue
- public boolean hasVerifiedPrincipal() {
- return null != getUniqueVerifiedCredential(AuthnPrincipal.class);
- }
-
- /**
- * Does this view have a verified password?
- *
- * @return True if this view has at least one verification containing a
- * password, and if no other verification contains a different password.
- */
- @CheckReturnValue
- protected boolean hasVerifiedPassword() {
- return null != getUniqueVerifiedCredential(AuthnPrincipal.class);
- }
-
- /**
- * Does this view have a jointly verified principal and password?
- *
- * @return True if this view has at least one verification containing both a
- * principal and password, and if no other verification contains a
- * different principal or password.
- */
- @CheckReturnValue
- public boolean hasVerifiedPrincipalAndPassword() {
- AuthnPrincipal principal = getUniqueVerifiedCredential(AuthnPrincipal.class);
- CredPassword password = getUniqueVerifiedCredential(CredPassword.class);
- return principal != null
- && password != null
- && areJointlyVerified(principal, password);
- }
-
- /**
- * Gets a verified principal.
- *
- * @return The verified principal. Returns {@code null} if
- * {@code hasVerifiedPrincipal()} is false.
- */
- @CheckReturnValue
- @Nullable
- public AuthnPrincipal getVerifiedPrincipal() {
- return getUniqueVerifiedCredential(AuthnPrincipal.class);
- }
-
- /**
- * Gets the verified groups for this view.
- *
- * @return The verified groups, may be empty.
- */
- @CheckReturnValue
- @Nonnull
- public ImmutableSet<String> getVerifiedGroups() {
- ImmutableSet.Builder<String> builder = ImmutableSet.builder();
- for (GroupMemberships credential : getVerifiedCredentials(GroupMemberships.class)) {
- builder.addAll(credential.getGroups());
- }
- return builder.build();
- }
-
- /**
- * Gets the expiration time of a credential.
- *
- * @param credential A credential to get the expiration time for.
- * @return The credential's expiration time, or {@code 0} if the credential
- * isn't verified.
- */
- @CheckReturnValue
- public long getCredentialExpirationTime(Credential credential) {
- Preconditions.checkNotNull(credential);
- return Verification.maximumExpirationTime(getJointVerifications(credential));
- }
-
- private <T extends Credential> T getUniqueVerifiedCredential(Class<T> clazz) {
- Credential uniqueCredential = null;
- for (Verification verification : getVerifications()) {
- if (verification.isVerified()) {
- for (Credential credential : verification.getCredentials()) {
- if (clazz.isInstance(credential)) {
- if (uniqueCredential == null) {
- uniqueCredential = credential;
- } else if (!uniqueCredential.equals(credential)) {
- return null;
- }
- }
- }
- }
- }
- return clazz.cast(uniqueCredential);
- }
-
- private <T extends Credential> Iterable<T> getVerifiedCredentials(Class<T> clazz) {
- ImmutableList.Builder<T> builder = ImmutableList.builder();
- for (Verification verification : getVerifications()) {
- if (verification.isVerified()) {
- for (Credential credential : verification.getCredentials()) {
- if (clazz.isInstance(credential)) {
- builder.add(clazz.cast(credential));
- }
- }
- }
- }
- return builder.build();
- }
-
- private boolean areJointlyVerified(Credential... credentials) {
- return Iterables.any(getVerifications(),
- Predicates.and(
- Verification.isVerifiedPredicate(),
- Verification.getContainsAllCredentialsPredicate(credentials)));
- }
-
- private Iterable<Verification> getJointVerifications(Credential... credentials) {
- return Iterables.filter(getVerifications(),
- Predicates.and(
- Verification.isVerifiedPredicate(),
- Verification.getContainsAllCredentialsPredicate(credentials)));
- }
-
- /**
- * Gets this view's verification status.
- *
- * @return The verification status.
- */
- @CheckReturnValue
- @Nonnull
- public VerificationStatus getVerificationStatus() {
- return Verification.getStatus(getVerifications());
- }
-
- /**
- * Does this view have no refutations and at least one verification?
- *
- * @return True if this view is verified.
- */
- @CheckReturnValue
- public boolean isVerified() {
- return getVerificationStatus() == VerificationStatus.VERIFIED;
- }
-
- /**
- * Does this view have at least one refutation?
- *
- * @return True if this view is refuted.
- */
- @CheckReturnValue
- public boolean isRefuted() {
- return getVerificationStatus() == VerificationStatus.REFUTED;
- }
-
- /**
- * Does this view have no refutations and no verifications?
- *
- * @return True if this view is indeterminate.
- */
- @CheckReturnValue
- public boolean isIndeterminate() {
- return getVerificationStatus() == VerificationStatus.INDETERMINATE;
- }
-
- // **************** Logging ****************
-
- /**
- * Annotates a log message with this view's session ID.
- *
- * @param format The format string to pass to {@link String#format}.
- * @param args The arguments to pass to {@link String#format}.
- * @return The annotated log message.
- */
- @CheckReturnValue
- @Nonnull
- public String logMessage(String format, Object... args) {
- return snapshot.logMessage(format, args);
- }
-}
diff --git a/src/com/google/enterprise/secmgr/authncontroller/SessionViewForCredentialGroup.java b/src/com/google/enterprise/secmgr/authncontroller/SessionViewForCredentialGroup.java
deleted file mode 100644
index bf427c4..0000000
--- a/src/com/google/enterprise/secmgr/authncontroller/SessionViewForCredentialGroup.java
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.google.enterprise.secmgr.authncontroller;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.enterprise.secmgr.config.AuthnAuthority;
-import com.google.enterprise.secmgr.config.AuthnMechanism;
-import com.google.enterprise.secmgr.config.CredentialGroup;
-import com.google.enterprise.secmgr.identity.AuthnPrincipal;
-import com.google.enterprise.secmgr.identity.CredPassword;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A view of a session snapshot that's specialized for a credential group.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-final class SessionViewForCredentialGroup extends SessionView {
-
- @Nonnull private final CredentialGroup credentialGroup;
-
- SessionViewForCredentialGroup(SessionSnapshot snapshot, CredentialGroup credentialGroup) {
- super(snapshot);
- Preconditions.checkNotNull(credentialGroup);
- Preconditions.checkState(
- snapshot.getConfig().getCredentialGroups().contains(credentialGroup));
- this.credentialGroup = credentialGroup;
- }
-
- @Override
- protected SessionView withNewSnapshot(SessionSnapshot snapshot) {
- return snapshot.getView(credentialGroup);
- }
-
- @Override
- public boolean isSpecializedForCredentialGroup() {
- return true;
- }
-
- @Override
- public AuthnAuthority getAuthority() {
- return credentialGroup.getAuthority();
- }
-
- @Override
- public AuthnMechanism getMechanism() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public CredentialGroup getCredentialGroup() {
- return credentialGroup;
- }
-
- @Override
- protected Predicate<AuthnAuthority> getCookieFilter() {
- return snapshot.getConfig().getAuthorityPredicate(credentialGroup);
- }
-
- @Override
- protected Predicate<AuthnAuthority> getCredentialFilter() {
- return snapshot.getConfig().getAuthorityPredicate(credentialGroup);
- }
-
- @Override
- public boolean isSatisfied() {
- if (credentialGroup.getMechanisms().isEmpty()) {
- // An empty group is never satisfied.
- logMessage("Credential group %s not satisfied because it is empty.",
- credentialGroup.getName());
- return false;
- }
-
- if (isRefuted()) {
- logMessage("Credential group %s not satisfied because it is refuted.",
- credentialGroup.getName());
- return false;
- }
-
- // If principal is required, it must be present and non-empty.
- if (credentialGroup.getRequiresUsername() && !hasVerifiedPrincipal()) {
- logMessage("Credential group %s not satisfied because it requires a username.",
- credentialGroup.getName());
- return false;
- }
-
- // If password is required, it must be present and non-empty.
- if (credentialGroup.getRequiresPassword() && !hasVerifiedPassword()) {
- logMessage("Credential group %s not satisfied because it requires a password.",
- credentialGroup.getName());
- return false;
- }
-
- // If group is optional, empty principal and password are sufficient.
- // Note that both the principal and the password must be present; otherwise
- // that means we haven't yet gathered credentials, so we must not return
- // satisfied. When they are both empty, it means we gathered credentials
- // and the user didn't fill them in.
- if (credentialGroup.getIsOptional() && hasEmptyPrincipal() && hasEmptyPassword()) {
- logMessage("Credential group %s satisfied because it's optional and was left blank.",
- credentialGroup.getName());
- return true;
- }
-
- // TODO(cph): This doesn't check the credentials -- so the username and/or
- // password might not be verified. Unfortunately, the program's current
- // logic doesn't understand that credentials must be verified independently
- // of the satisfaction of their identity group.
- return isVerified();
- }
-
- private boolean hasEmptyPrincipal() {
- AuthnPrincipal principal = getPrincipal();
- return principal != null && principal.getName().isEmpty();
- }
-
- private boolean hasEmptyPassword() {
- CredPassword password = getPasswordCredential();
- return password != null && password.getText().isEmpty();
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("{SessionView of ");
- builder.append(snapshot);
- builder.append(" specialized for: ");
- builder.append(credentialGroup);
- builder.append("}");
- return builder.toString();
- }
-}
diff --git a/src/com/google/enterprise/secmgr/authncontroller/SessionViewForMechanism.java b/src/com/google/enterprise/secmgr/authncontroller/SessionViewForMechanism.java
deleted file mode 100644
index a3acde1..0000000
--- a/src/com/google/enterprise/secmgr/authncontroller/SessionViewForMechanism.java
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.google.enterprise.secmgr.authncontroller;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.enterprise.secmgr.config.AuthnAuthority;
-import com.google.enterprise.secmgr.config.AuthnMechanism;
-import com.google.enterprise.secmgr.config.CredentialGroup;
-import com.google.enterprise.secmgr.identity.Verification;
-import com.google.enterprise.secmgr.identity.VerificationStatus;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A view of a session snapshot that's specialized for an authority.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-final class SessionViewForMechanism extends SessionView {
- @Nonnull private final AuthnMechanism mechanism;
- @Nonnull private final CredentialGroup credentialGroup;
-
- SessionViewForMechanism(SessionSnapshot snapshot, AuthnMechanism mechanism) {
- super(snapshot);
- Preconditions.checkNotNull(mechanism);
- this.mechanism = mechanism;
- credentialGroup = snapshot.getConfig().getCredentialGroup(mechanism);
- }
-
- @Override
- protected SessionView withNewSnapshot(SessionSnapshot snapshot) {
- return snapshot.getView(mechanism);
- }
-
- @Override
- public boolean isSpecializedForMechanism() {
- return true;
- }
-
- @Override
- public AuthnAuthority getAuthority() {
- return mechanism.getAuthority();
- }
-
- @Override
- public CredentialGroup getCredentialGroup() {
- return credentialGroup;
- }
-
- @Override
- public AuthnMechanism getMechanism() {
- return mechanism;
- }
-
- @Override
- protected Predicate<AuthnAuthority> getCookieFilter() {
- return Predicates.equalTo(getAuthority());
- }
-
- @Override
- protected Predicate<AuthnAuthority> getCredentialFilter() {
- return snapshot.getConfig().getAuthorityPredicate(credentialGroup);
- }
-
- @Override
- public VerificationStatus getVerificationStatus() {
- return Verification.getStatus(
- getSummary().getVerifications(Predicates.equalTo(getAuthority()), getTimeStamp()));
- }
-
- @Override
- public boolean isSatisfied() {
- return isVerified();
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("{SessionView of ");
- builder.append(snapshot);
- builder.append(" specialized for: ");
- builder.append(mechanism);
- builder.append("}");
- return builder.toString();
- }
-}
diff --git a/src/com/google/enterprise/secmgr/authncontroller/SessionViewUnspecialized.java b/src/com/google/enterprise/secmgr/authncontroller/SessionViewUnspecialized.java
deleted file mode 100644
index 063ab9f..0000000
--- a/src/com/google/enterprise/secmgr/authncontroller/SessionViewUnspecialized.java
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.google.enterprise.secmgr.authncontroller;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.Lists;
-import com.google.enterprise.secmgr.config.AuthnAuthority;
-import com.google.enterprise.secmgr.config.AuthnMechanism;
-import com.google.enterprise.secmgr.config.CredentialGroup;
-
-import java.util.List;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A view of a session snapshot that's not specialized.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-final class SessionViewUnspecialized extends SessionView {
-
- SessionViewUnspecialized(final SessionSnapshot snapshot) {
- super(snapshot);
- }
-
- @Override
- protected SessionView withNewSnapshot(SessionSnapshot snapshot) {
- return snapshot.getView();
- }
-
- @Override
- public boolean isUnspecialized() {
- return true;
- }
-
- @Override
- public AuthnAuthority getAuthority() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public CredentialGroup getCredentialGroup() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public AuthnMechanism getMechanism() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- protected Predicate<AuthnAuthority> getCookieFilter() {
- return Predicates.alwaysTrue();
- }
-
- @Override
- protected Predicate<AuthnAuthority> getCredentialFilter() {
- return Predicates.alwaysTrue();
- }
-
- @Override
- public boolean isSatisfied() {
- List<CredentialGroup> nonEmpty = Lists.newArrayList();
- for (CredentialGroup credentialGroup : snapshot.getConfig().getCredentialGroups()) {
- if (!credentialGroup.getMechanisms().isEmpty()) {
- nonEmpty.add(credentialGroup);
- }
- }
- if (nonEmpty.isEmpty()) {
- logMessage("No non-empty credential groups, so nothing to be satisfied.");
- return false;
- }
- for (CredentialGroup credentialGroup : nonEmpty) {
- if (!snapshot.getView(credentialGroup).isSatisfied()) {
- logMessage("Credential group %s reports not satisfied, so session is not satisfied.",
- credentialGroup.getName());
- return false;
- }
- }
- return true;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("{SessionView of ");
- builder.append(snapshot);
- builder.append("}");
- return builder.toString();
- }
-}
diff --git a/src/com/google/enterprise/secmgr/common/Base64.java b/src/com/google/enterprise/secmgr/common/Base64.java
deleted file mode 100644
index fa88ccd..0000000
--- a/src/com/google/enterprise/secmgr/common/Base64.java
+++ /dev/null
@@ -1,477 +0,0 @@
-// Copyright 2002 Google Inc.
-//
-// 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.
-
-// This code was converted from code at http://iharder.sourceforge.net/base64/
-// Lots of extraneous features were removed.
-/* The original code said:
- * <p>
- * I am placing this code in the Public Domain. Do with it as you will.
- * This software comes with no guarantees or warranties but with
- * plenty of well-wishing instead!
- * Please visit
- * <a href="http://iharder.net/xmlizable">http://iharder.net/xmlizable</a>
- * periodically to check for updates or to contribute improvements.
- * </p>
- *
- * @author Robert Harder
- * @author rharder@usa.net
- * @version 1.3
- */
-
-package com.google.enterprise.secmgr.common;
-
-/**
- * Base64 converter class. This code is not a full-blown MIME encoder;
- * it simply converts binary data to base64 data and back.
- */
-public class Base64 {
- /** Specify encoding (value is {@code true}). */
- public static final boolean ENCODE = true;
-
- /** Specify decoding (value is {@code false}). */
- public static final boolean DECODE = false;
-
- /** The equals sign (=) as a byte. */
- private static final byte EQUALS_SIGN = (byte) '=';
-
- /** The new line character (\n) as a byte. */
- private static final byte NEW_LINE = (byte) '\n';
-
- /** The 64 valid Base64 values. */
- public static final byte[] ALPHABET =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
- .getBytes();
-
- /** The 64 valid web safe Base64 values. */
- public static final byte[] WEBSAFE_ALPHABET =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
- .getBytes();
-
- /**
- * Translates a Base64 value to either its 6-bit reconstruction value
- * or a negative number indicating some other meaning. This can decode
- * content that was endoded with either the standard ALPHABET or the
- * WEBSAFE_ALPHABET.
- */
- private static final byte[] DECODABET = {
- -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
- -5, -5, // Whitespace: Tab and Linefeed
- -9, -9, // Decimal 11 - 12
- -5, // Whitespace: Carriage Return
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
- -9, -9, -9, -9, -9, // Decimal 27 - 31
- -5, // Whitespace: Space
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
- 62, // Plus sign at decimal 43
- -9, // Decimal 44
- 62, // Dash '-' sign at decimal 45 (from WebSafe encoding)
- -9, // Decimal 46
- 63, // Slash at decimal 47
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
- -9, -9, -9, // Decimal 58 - 60
- -1, // Equals sign at decimal 61
- -9, -9, -9, // Decimal 62 - 64
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
- -9, -9, -9, -9, // Decimal 91-94
- 63, // Underscore '_' at decimal 95 (from WebSafe encoding)
- -9, // Decimal 96
- 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
- -9, -9, -9, -9, -9 // Decimal 123 - 127
- };
-
- // Indicates white space in encoding.
- private static final byte WHITE_SPACE_ENC = -5;
-
- // Indicates equals sign in encoding.
- private static final byte EQUALS_SIGN_ENC = -1;
-
- private Base64() {
- // Defeats instantiation.
- }
-
- /* ******** E N C O D I N G M E T H O D S ******** */
-
- /**
- * Encodes up to three bytes of the array <var>source</var>
- * and writes the resulting four Base64 bytes to <var>destination</var>.
- * The source and destination arrays can be manipulated
- * anywhere along their length by specifying
- * <var>srcOffset</var> and <var>destOffset</var>.
- * This method does not check to make sure your arrays
- * are large enough to accommodate <var>srcOffset</var> + 3 for
- * the <var>source</var> array or <var>destOffset</var> + 4 for
- * the <var>destination</var> array.
- * The actual number of significant bytes in your array is
- * given by <var>numSigBytes</var>.
- *
- * @param source the array to convert
- * @param srcOffset the index where conversion begins
- * @param numSigBytes the number of significant bytes in your array
- * @param destination the array to hold the conversion
- * @param destOffset the index where output will be put
- * @param alphabet is the encoding alphabet
- * @return the <var>destination</var> array
- * @since 1.3
- */
- static byte[] encode3to4(byte[] source, int srcOffset,
- int numSigBytes, byte[] destination, int destOffset, byte[] alphabet) {
- // 1 2 3
- // 01234567890123456789012345678901 Bit position
- // --------000000001111111122222222 Array position from threeBytes
- // --------| || || || | Six bit groups to index alphabet
- // >>18 >>12 >> 6 >> 0 Right shift necessary
- // 0x3f 0x3f 0x3f Additional AND
-
- // Create buffer with zero-padding if there are only one or two
- // significant bytes passed in the array.
- // We have to shift left 24 in order to flush out the 1's that appear
- // when Java treats a value as negative that is cast from a byte to an int.
- int inBuff =
- (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)
- | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
- | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);
-
- switch (numSigBytes) {
- case 3:
- destination[destOffset] = alphabet[(inBuff >>> 18)];
- destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];
- destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f];
- destination[destOffset + 3] = alphabet[(inBuff) & 0x3f];
- return destination;
- case 2:
- destination[destOffset] = alphabet[(inBuff >>> 18)];
- destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];
- destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f];
- destination[destOffset + 3] = EQUALS_SIGN;
- return destination;
- case 1:
- destination[destOffset] = alphabet[(inBuff >>> 18)];
- destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];
- destination[destOffset + 2] = EQUALS_SIGN;
- destination[destOffset + 3] = EQUALS_SIGN;
- return destination;
- default:
- return destination;
- } // end switch
- } // end encode3to4
-
- /**
- * Encodes a byte array into Base64 notation.
- * Equivalent to calling
- * {@code encodeBytes(source, 0, source.length)}
- *
- * @param source The data to convert
- * @since 1.4
- */
- public static String encode(byte[] source) {
- return encode(source, 0, source.length, ALPHABET, true);
- }
-
- /**
- * Encodes a byte array into web safe Base64 notation.
- *
- * @param source The data to convert
- * @param doPadding is {@code true} to pad result with '=' chars
- * if it does not fall on 3 byte boundaries
- */
- public static String encodeWebSafe(byte[] source, boolean doPadding) {
- return encode(source, 0, source.length, WEBSAFE_ALPHABET, doPadding);
- }
-
- /**
- * Encodes a byte array into Base64 notation.
- *
- * @param source The data to convert
- * @param off Offset in array where conversion should begin
- * @param len Length of data to convert
- * @param alphabet is the encoding alphabet
- * @param doPadding is {@code true} to pad result with '=' chars
- * if it does not fall on 3 byte boundaries
- * @since 1.4
- */
- public static String encode(byte[] source, int off, int len, byte[] alphabet,
- boolean doPadding) {
- byte[] outBuff = encode(source, off, len, alphabet, Integer.MAX_VALUE);
- int outLen = outBuff.length;
-
- // If doPadding is false, set length to truncate '='
- // padding characters
- while (doPadding == false && outLen > 0) {
- if (outBuff[outLen - 1] != '=') {
- break;
- }
- outLen -= 1;
- }
-
- return new String(outBuff, 0, outLen);
- }
-
- /**
- * Encodes a byte array into Base64 notation.
- *
- * @param source The data to convert
- * @param off Offset in array where conversion should begin
- * @param len Length of data to convert
- * @param alphabet is the encoding alphabet
- * @param maxLineLength maximum length of one line.
- * @return the BASE64-encoded byte array
- */
- public static byte[] encode(byte[] source, int off, int len, byte[] alphabet,
- int maxLineLength) {
- int len43 = ((len + 2) / 3) * 4;
- byte[] outBuff = new byte[len43 + (len43 / maxLineLength)];
-
- encode(source, off, len, outBuff, 0, alphabet, maxLineLength);
- return outBuff;
- }
-
- /**
- * Encodes a byte array into Base64 notation into a destination byte array.
- * Warning: No check is made to make sure the destination is big enough
- * to hold the conversion.
- * This was optimally constructed for use by Base64FilterInputStream.
- *
- * @param source The data to convert
- * @param sourceOffset Offset in source array where conversion should begin
- * @param sourceLength Length of data to convert
- * @param dest The destination array for converted data
- * @param destOffset Offset in destination array to write
- * @param alphabet is the encoding alphabet
- * @param maxLineLength maximum length of one line.
- * @return the number of bytes written to destination.
- */
- static int encode(byte[] source, int sourceOffset, int sourceLength,
- byte[] dest, int destOffset, byte[] alphabet, int maxLineLength) {
- int s = 0;
- int d = destOffset;
- int len = sourceLength - 2;
- int lineLength = 0;
-
- for (; s < len; s += 3, d += 4) {
- // The following block of code is the same as
- // encode3to4( source, s + off, 3, dest, d, alphabet );
- // but inlined for faster encoding (~20% improvement)
- int inBuff =
- ((source[s + sourceOffset] << 24) >>> 8)
- | ((source[s + 1 + sourceOffset] << 24) >>> 16)
- | ((source[s + 2 + sourceOffset] << 24) >>> 24);
- dest[d] = alphabet[(inBuff >>> 18)];
- dest[d + 1] = alphabet[(inBuff >>> 12) & 0x3f];
- dest[d + 2] = alphabet[(inBuff >>> 6) & 0x3f];
- dest[d + 3] = alphabet[(inBuff) & 0x3f];
-
- if ((lineLength += 4) >= maxLineLength) {
- dest[d + 4] = NEW_LINE;
- d++;
- lineLength = 0;
- } // end if: end of line
- } // end for: each piece of array
-
- if (s < sourceLength) {
- encode3to4(source, s + sourceOffset, sourceLength - s, dest, d, alphabet);
- d += 4;
- if ((lineLength += 4) >= maxLineLength) {
- dest[d++] = NEW_LINE;
- }
- }
-
- return d - destOffset;
- }
-
- /* ******** D E C O D I N G M E T H O D S ******** */
-
- /**
- * Decodes four bytes from array <var>source</var>
- * and writes the resulting bytes (up to three of them)
- * to <var>destination</var>.
- * The source and destination arrays can be manipulated
- * anywhere along their length by specifying
- * <var>srcOffset</var> and <var>destOffset</var>.
- * This method does not check to make sure your arrays
- * are large enough to accommodate <var>srcOffset</var> + 4 for
- * the <var>source</var> array or <var>destOffset</var> + 3 for
- * the <var>destination</var> array.
- * This method returns the actual number of bytes that
- * were converted from the Base64 encoding.
- *
- *
- * @param source the array to convert
- * @param srcOffset the index where conversion begins
- * @param destination the array to hold the conversion
- * @param destOffset the index where output will be put
- * @param decodabet the decodabet for decoding Base64 content
- * @return the number of decoded bytes converted
- * @since 1.3
- */
- private static int decode4to3(byte[] source, int srcOffset,
- byte[] destination, int destOffset, byte[] decodabet) {
- // Example: Dk==
- if (source[srcOffset + 2] == EQUALS_SIGN) {
- int outBuff =
- ((decodabet[source[srcOffset]] << 24) >>> 6)
- | ((decodabet[source[srcOffset + 1]] << 24) >>> 12);
-
- destination[destOffset] = (byte) (outBuff >>> 16);
- return 1;
- } else if (source[srcOffset + 3] == EQUALS_SIGN) {
- // Example: DkL=
- int outBuff =
- ((decodabet[source[srcOffset]] << 24) >>> 6)
- | ((decodabet[source[srcOffset + 1]] << 24) >>> 12)
- | ((decodabet[source[srcOffset + 2]] << 24) >>> 18);
-
- destination[destOffset] = (byte) (outBuff >>> 16);
- destination[destOffset + 1] = (byte) (outBuff >>> 8);
- return 2;
- } else {
- // Example: DkLE
- int outBuff =
- ((decodabet[source[srcOffset]] << 24) >>> 6)
- | ((decodabet[source[srcOffset + 1]] << 24) >>> 12)
- | ((decodabet[source[srcOffset + 2]] << 24) >>> 18)
- | ((decodabet[source[srcOffset + 3]] << 24) >>> 24);
-
- destination[destOffset] = (byte) (outBuff >> 16);
- destination[destOffset + 1] = (byte) (outBuff >> 8);
- destination[destOffset + 2] = (byte) (outBuff);
- return 3;
- }
- } // end decodeToBytes
-
- /**
- * Decodes data from Base64 notation.
- * Understands either standard or web-safe encoding.
- *
- * @param s the string to decode (decoded in default encoding)
- * @return the decoded data
- * @since 1.4
- */
- public static byte[] decode(String s) throws Base64DecoderException {
- byte[] bytes = s.getBytes();
- return decode(bytes, 0, bytes.length, DECODABET);
- }
-
- /**
- * Decodes Base64 content in byte array format and returns
- * the decoded byte array.
- * Understands either standard or web-safe encoding.
- *
- * @param source The Base64 encoded data
- * @return decoded data
- * @since 1.3
- * @throws Base64DecoderException
- */
- public static byte[] decode(byte[] source) throws Base64DecoderException {
- return decode(source, 0, source.length, DECODABET);
- }
-
- /**
- * Decodes Base64 content in byte array format and returns
- * the decoded byte array.
- * Understands either standard or web-safe encoding.
- *
- * @param source The Base64 encoded data
- * @param off The offset of where to begin decoding
- * @param len The length of characters to decode
- * @return decoded data
- * @since 1.3
- * @throws Base64DecoderException
- */
- public static byte[] decode(byte[] source, int off, int len)
- throws Base64DecoderException {
- return decode(source, off, len, DECODABET);
- }
-
- /**
- * Decodes Base64 content using the supplied decodabet and returns
- * the decoded byte array.
- * Understands either standard or web-safe encoding.
- *
- * @param source The Base64 encoded data
- * @param off The offset of where to begin decoding
- * @param len The length of characters to decode
- * @param decodabet the decodabet for decoding Base64 content
- * @return decoded data
- */
- public static byte[] decode(byte[] source, int off, int len, byte[] decodabet)
- throws Base64DecoderException {
- int len34 = len * 3 / 4;
- byte[] outBuff = new byte[2 + len34]; // Upper limit on size of output
- int outBuffPosn = 0;
-
- byte[] b4 = new byte[4];
- int b4Posn = 0;
- int i = 0;
- byte sbiCrop = 0;
- byte sbiDecode = 0;
- for (i = 0; i < len; i++) {
- sbiCrop = (byte) (source[i + off] & 0x7f); // Only the low seven bits
- sbiDecode = decodabet[sbiCrop];
-
- if (sbiDecode >= WHITE_SPACE_ENC) { // White space Equals sign or better
- if (sbiDecode >= EQUALS_SIGN_ENC) {
- // An equals sign (for padding) must not occur at position 0 or 1
- // and must be the last byte[s] in the encoded value.
- if (sbiCrop == EQUALS_SIGN) {
- int bytesLeft = len - i;
- byte lastByte = (byte) (source[len - 1 + off] & 0x7f);
- if (b4Posn == 0 || b4Posn == 1) {
- throw new Base64DecoderException(
- "invalid padding byte '=' at byte offset " + i);
- } else if ((b4Posn == 3 && bytesLeft > 2)
- || (b4Posn == 4 && bytesLeft > 1)) {
- throw new Base64DecoderException(
- "padding byte '=' falsely signals end of encoded value "
- + "at offset " + i);
- } else if (lastByte != EQUALS_SIGN && lastByte != NEW_LINE) {
- throw new Base64DecoderException(
- "encoded value has invalid trailing byte");
- }
- break;
- }
-
- b4[b4Posn++] = sbiCrop;
- if (b4Posn == 4) {
- outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet);
- b4Posn = 0;
- }
- }
- } else {
- throw new Base64DecoderException("Bad Base64 input character at " + i
- + ": " + source[i + off] + "(decimal)");
- }
- }
-
- // Because web safe encoding allows non padding base64 encodes, we
- // need to pad the rest of the b4 buffer with equal signs when
- // b4Posn != 0. There can be at most 2 equal signs at the end of
- // four characters, so the b4 buffer must have two or three
- // characters. This also catches the case where the input is
- // padded with EQUALS_SIGN.
- if (b4Posn != 0) {
- if (b4Posn == 1) {
- throw new Base64DecoderException("single trailing character at offset "
- + (len - 1));
- }
- b4[b4Posn++] = EQUALS_SIGN;
- outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet);
- }
-
- byte[] out = new byte[outBuffPosn];
- System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
- return out;
- }
-}
diff --git a/src/com/google/enterprise/secmgr/common/Base64DecoderException.java b/src/com/google/enterprise/secmgr/common/Base64DecoderException.java
deleted file mode 100644
index 39ac218..0000000
--- a/src/com/google/enterprise/secmgr/common/Base64DecoderException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2002 Google Inc.
-//
-// 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.google.enterprise.secmgr.common;
-
-/**
- * Exception thrown when encountering an invalid Base64 input character.
- *
- * <p>This class may be used with the Google Web Toolkit (GWT).
- */
-public class Base64DecoderException extends Exception {
- public Base64DecoderException() {
- super();
- }
-
- public Base64DecoderException(String s) {
- super(s);
- }
-}
diff --git a/src/com/google/enterprise/secmgr/common/Chain.java b/src/com/google/enterprise/secmgr/common/Chain.java
deleted file mode 100644
index 064119e..0000000
--- a/src/com/google/enterprise/secmgr/common/Chain.java
+++ /dev/null
@@ -1,428 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.google.enterprise.secmgr.common;
-
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnegative;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-import javax.annotation.concurrent.NotThreadSafe;
-
-/**
- * An immutable accumulator that adds elements to the end of a "chain" and can
- * later convert that to a {@link List}.
- *
- * @param <E> The type of the elements stored in this chain.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public abstract class Chain<E> implements Iterable<E> {
-
- @Nonnull private static final Chain<?> EMPTY_CHAIN = new EmptyChain<Object>();
-
- /**
- * Gets a new chain with no elements.
- */
- @CheckReturnValue
- @SuppressWarnings("unchecked")
- @Nonnull
- public static <F> Chain<F> empty() {
- return (Chain<F>) EMPTY_CHAIN;
- }
-
- /**
- * Gets a new chain with the given elements.
- *
- * @param elements The elements to make a chain from.
- * @return A chain of those elements.
- */
- @CheckReturnValue
- @Nonnull
- public static <F> Chain<F> copyOf(Iterable<F> elements) {
- Chain<F> chain = empty();
- for (F element : elements) {
- chain = chain.add(element);
- }
- return chain;
- }
-
- /**
- * Gets the number of elements in this chain.
- *
- * @return The number of elements.
- */
- @CheckReturnValue
- @Nonnegative
- public abstract int size();
-
- /**
- * Is this an empty chain?
- *
- * @return True if this chain has no elements.
- */
- @CheckReturnValue
- public abstract boolean isEmpty();
-
- /**
- * Gets the last element in this chain. That is, for any chain {@code C} and
- * element {@code E}, {@code C.add(E).getLast() == E}.
- *
- * @return The last element in the chain.
- * @throws UnsupportedOperationException if this is an empty chain.
- */
- @CheckReturnValue
- @Nonnull
- public abstract E getLast();
-
- /**
- * Gets the rest of this chain. That is, for any chain {@code C} and element
- * {@code E}, {@code C.add(E).getRest() == C}.
- *
- * @return The rest of this chain.
- * @throws UnsupportedOperationException if this is an empty chain.
- */
- @CheckReturnValue
- @Nonnull
- public abstract Chain<E> getRest();
-
- @Immutable
- private static final class EmptyChain<F> extends Chain<F> {
- @Override
- public int size() {
- return 0;
- }
-
- @Override
- public boolean isEmpty() {
- return true;
- }
-
- @Override
- public F getLast() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Chain<F> getRest() {
- throw new UnsupportedOperationException();
- }
- }
-
- @Immutable
- @ParametersAreNonnullByDefault
- private static final class NonEmptyChain<F> extends Chain<F> {
- @Nonnegative final int numberOfElements;
- @Nullable final F element;
- @Nonnull final Chain<F> rest;
-
- NonEmptyChain(@Nullable F element, Chain<F> rest) {
- Preconditions.checkNotNull(rest);
- this.numberOfElements = rest.size() + 1;
- this.element = element;
- this.rest = rest;
- }
-
- @Override
- public int size() {
- return numberOfElements;
- }
-
- @Override
- public boolean isEmpty() {
- return false;
- }
-
- @Override
- @Nullable
- public F getLast() {
- return element;
- }
-
- @Override
- @Nonnull
- public Chain<F> getRest() {
- return rest;
- }
- }
-
- /**
- * Adds a new element to the chain. Since this is an immutable structure, a
- * new chain is returned that contains the new element as well as all the
- * elements of this chain. The new chain has a "last" of {@code element} and
- * a "rest" of {@code this}.
- *
- * @param element The element to be added.
- * @return The new chain with the added element.
- * @throws NullPointerException if element is null.
- */
- @CheckReturnValue
- @Nonnull
- public Chain<E> add(@Nullable E element) {
- return new NonEmptyChain<E>(element, this);
- }
-
- /**
- * Adds some new elements to the chain.
- *
- * @param elements The elements to be added.
- * @return The new chain with the added elements.
- */
- @CheckReturnValue
- @Nonnull
- public Chain<E> addAll(Iterable<E> elements) {
- Chain<E> chain = this;
- for (E element : elements) {
- chain = chain.add(element);
- }
- return chain;
- }
-
- /**
- * Gets an element from the chain. A given index specifies the
- * element, where zero refers to the first element in the chain and
- * {@code size() - 1} refers to the last.
- *
- * @param index The index of the element to get.
- * @return The specified element.
- * @throws IllegalArgumentException if index is negative or too large.
- */
- @CheckReturnValue
- @Nonnull
- public E get(@Nonnegative int index) {
- Preconditions.checkArgument(index >= 0 && index < size());
- Chain<E> chain = this;
- for (int i = 0; i < size() - (index + 1); i += 1) {
- chain = chain.getRest();
- }
- return chain.getLast();
- }
-
- /**
- * Converts this chain to a set.
- *
- * @return The elements of this chain as a set.
- */
- @CheckReturnValue
- @Nonnull
- public Set<E> toSet() {
- return Sets.newHashSet(this);
- }
-
- /**
- * Converts this chain to a list, preserving the chain's order.
- *
- * @return The elements of this chain as a list.
- */
- @CheckReturnValue
- @Nonnull
- public List<E> toList() {
- LinkedList<E> list = Lists.newLinkedList();
- Chain<E> chain = this;
- for (int i = 0; i < size(); i += 1) {
- list.addFirst(chain.getLast());
- chain = chain.getRest();
- }
- return list;
- }
-
- /**
- * Given a chain that is an ancestor of this chain, returns the elements that
- * have been added to the ancestor to make this chain.
- *
- * <p>For any ancestor chain {@code C} it is always true that
- * {@code this.equals(C.addAll(this.toList(C)))}.
- *
- * @param ancestor The ancestor chain.
- * @return A list of the elements elements added .
- * @throws IllegalArgumentException if {@code chain} is not an ancestor.
- */
- @CheckReturnValue
- @Nonnull
- public List<E> toList(Chain<E> ancestor) {
- Preconditions.checkNotNull(ancestor);
- LinkedList<E> list = Lists.newLinkedList();
- Chain<E> chain = this;
- while (chain != ancestor) {
- if (chain.isEmpty()) {
- throw new IllegalArgumentException("Not an ancestor chain: " + ancestor);
- }
- list.addFirst(chain.getLast());
- chain = chain.getRest();
- }
- return list;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof Chain<?>)) { return false; }
- Chain<?> other = (Chain<?>) object;
- if (size() != other.size()) { return false; }
- Chain<E> c1 = this;
- Chain<?> c2 = other;
- for (int i = 0; i < size(); i += 1) {
- if (!c1.getLast().equals(c2.getLast())) { return false; }
- c1 = c1.getRest();
- c2 = c2.getRest();
- }
- return true;
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(toList());
- }
-
- @Override
- public String toString() {
- return toList().toString();
- }
-
- /**
- * Gets an iterator for this chain. The iterator starts with the last element
- * and moves towards the first. If you want to iterate from first element to
- * last, use {@link #toList()}.
- */
- @Override
- public Iterator<E> iterator() {
- return new LocalIterator<E>(this);
- }
-
- @NotThreadSafe
- private static final class LocalIterator<F> implements Iterator<F> {
- Chain<F> chain;
-
- LocalIterator(Chain<F> chain) {
- this.chain = chain;
- }
-
- @Override
- public boolean hasNext() {
- return !chain.isEmpty();
- }
-
- @Override
- public F next() {
- if (chain.isEmpty()) { throw new NoSuchElementException(); }
- F value = chain.getLast();
- chain = chain.getRest();
- return value;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
- * Converts an iterable of chains to an iterable of lists. The resulting
- * lists have the same ordering as the input chains.
- *
- * @param chains The chains to convert.
- * @return The resulting lists.
- */
- @CheckReturnValue
- @Nonnull
- public static <T> Iterable<List<T>> toLists(Iterable<Chain<T>> chains) {
- return Iterables.transform(chains, Chain.<T>toListFunction());
- }
-
- /**
- * Gets a function that invokes the {@link #toList} method on its argument.
- */
- @CheckReturnValue
- @Nonnull
- public static <T> Function<Chain<T>, List<T>> toListFunction() {
- return new Function<Chain<T>, List<T>>() {
- @Override
- public List<T> apply(Chain<T> chain) {
- return chain.toList();
- }
- };
- }
-
- /**
- * Converts an iterable of chains to an iterable of sets.
- *
- * @param chains The chains to convert.
- * @return The resulting sets.
- */
- @CheckReturnValue
- @Nonnull
- public static <T> Iterable<Set<T>> toSets(Iterable<Chain<T>> chains) {
- return Iterables.transform(chains, Chain.<T>toSetFunction());
- }
-
- /**
- * Gets a function that invokes the {@link #toSet} method on its argument.
- */
- @CheckReturnValue
- @Nonnull
- public static <T> Function<Chain<T>, Set<T>> toSetFunction() {
- return new Function<Chain<T>, Set<T>>() {
- @Override
- public Set<T> apply(Chain<T> chain) {
- return chain.toSet();
- }
- };
- }
-
- /**
- * Extends an iterable of chains with a given element. For each member of the
- * iterable, it creates a new member by adding the element to that member.
- *
- * @param chains The chains to be extended.
- * @param element The element to extend them with.
- * @return An iterable of the extended chains.
- */
- @CheckReturnValue
- @Nonnull
- public static <T> Iterable<Chain<T>> addToChains(Iterable<Chain<T>> chains, T element) {
- return Iterables.transform(chains, addFunction(element));
- }
-
- /**
- * Gets a function that adds a given element to a given chain.
- *
- * @param element The element to be added.
- * @return A function that extends its argument with {@code element}.
- */
- @CheckReturnValue
- @Nonnull
- public static <T> Function<Chain<T>, Chain<T>> addFunction(@Nullable final T element) {
- return new Function<Chain<T>, Chain<T>>() {
- @Override
- public Chain<T> apply(Chain<T> chain) {
- return chain.add(element);
- }
- };
- }
-}
diff --git a/src/com/google/enterprise/secmgr/common/CookieStore.java b/src/com/google/enterprise/secmgr/common/CookieStore.java
deleted file mode 100644
index 7664c7c..0000000
--- a/src/com/google/enterprise/secmgr/common/CookieStore.java
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.google.enterprise.secmgr.common;
-
-import java.util.Collection;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnegative;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-/**
- * A cookie store is an object that holds a collection of cookies. The store
- * never holds two cookies with the same key. When a cookie is added to a
- * store, if there's already a cookie in the store with that key, the new cookie
- * replaces the old one.
- * <p>
- * Because of this, the store may contain multiple cookies with the same name,
- * as long as the other parts of their keys differ.
- */
-@ParametersAreNonnullByDefault
-public interface CookieStore extends Collection<GCookie> {
- /**
- * Removes all cookies with expiration times earlier than a given time.
- *
- * @param timeStamp A time to use for expirations.
- */
- public void expireCookies(@Nonnegative long timeStamp);
-
- /**
- * Removes all cookies with expiration times earlier than the current time.
- */
- public void expireCookies();
-
- /**
- * Does this store contain a cookie with a given name?
- *
- * @param name The name to test for.
- * @return True only if there's at least one cookie with that name in the
- * store.
- */
- @CheckReturnValue
- public boolean contains(String name);
-
- /**
- * If this store contains a cookie with a given name, gets it. If there are
- * multiple cookies with that name, one of them is arbitrarily chosen.
- *
- * @param name The name to look for.
- * @return A cookie with that name, or {@code null} if there are none.
- */
- @CheckReturnValue
- @Nullable
- public GCookie get(String name);
-
- /**
- * Does this store contain a cookie with a given key?
- *
- * @param key The key to test for.
- * @return True only if there's a cookie with that key in the store.
- */
- @CheckReturnValue
- public boolean contains(GCookie.Key key);
-
- /**
- * If this store contains a cookie with a given key, gets it.
- *
- * @param key The key to look for.
- * @return The cookie with that key, or {@code null} if there isn't one.
- */
- @CheckReturnValue
- @Nullable
- public GCookie get(GCookie.Key key);
-}
diff --git a/src/com/google/enterprise/secmgr/common/CookieStoreImpl.java b/src/com/google/enterprise/secmgr/common/CookieStoreImpl.java
deleted file mode 100644
index fbd4d32..0000000
--- a/src/com/google/enterprise/secmgr/common/CookieStoreImpl.java
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.google.enterprise.secmgr.common;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-
-import org.joda.time.DateTimeUtils;
-
-import java.util.AbstractCollection;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.annotation.Nonnegative;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.NotThreadSafe;
-
-/**
- * An implementation of a mutable cookie store that automatically expires
- * cookies whenever a cookie is added or the store is iterated.
- */
-@NotThreadSafe
-@ParametersAreNonnullByDefault
-final class CookieStoreImpl extends AbstractCollection<GCookie>
- implements CookieStore {
-
- @Nonnull private final Map<GCookie.Key, GCookie> map;
-
- CookieStoreImpl() {
- map = Maps.newHashMap();
- }
-
- @Override
- public int size() {
- return map.size();
- }
-
- // For a given cookie name, a store can contain exactly one partial key with
- // that name, or no partial keys and any number of full keys.
- @Override
- public boolean add(GCookie cookie) {
- GCookie.Key key = cookie.getKey();
- GCookie oldCookie = map.get(key);
- if (cookie.equals(oldCookie)) {
- return false;
- }
- Iterables.removeIf(this, matchingKeyPredicate(key));
- if (oldCookie != null) {
- map.put(key, GCookie.builder(cookie).setCreationTime(oldCookie.getCreationTime()).build());
- } else {
- map.put(key, cookie);
- }
- return true;
- }
-
- private static Predicate<GCookie> matchingKeyPredicate(final GCookie.Key key) {
- return key.isPartial()
- ? new Predicate<GCookie>() {
- @Override
- public boolean apply(GCookie cookie) {
- GCookie.Key other = cookie.getKey();
- return key.getName().equals(other.getName());
- }
- }
- : new Predicate<GCookie>() {
- @Override
- public boolean apply(GCookie cookie) {
- GCookie.Key other = cookie.getKey();
- return key.getName().equals(other.getName())
- && (other.isPartial() || key.equals(other));
- }
- };
- }
-
- @Override
- public Iterator<GCookie> iterator() {
- return map.values().iterator();
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof Iterable<?>)) { return false; }
- return ImmutableSet.copyOf(map.values()).equals(ImmutableSet.copyOf((Iterable<?>) object));
- }
-
- @Override
- public int hashCode() {
- return ImmutableSet.copyOf(map.values()).hashCode();
- }
-
- @Override
- public void expireCookies(@Nonnegative long timeStamp) {
- Iterables.removeIf(this, GCookie.isExpiredPredicate(timeStamp));
- }
-
- @Override
- public void expireCookies() {
- expireCookies(DateTimeUtils.currentTimeMillis());
- }
-
- @Override
- public boolean contains(String name) {
- return get(name) != null;
- }
-
- @Override
- @Nullable
- public GCookie get(String name) {
- Preconditions.checkNotNull(name);
- for (GCookie cookie : map.values()) {
- if (name.equalsIgnoreCase(cookie.getName())) {
- return cookie;
- }
- }
- return null;
- }
-
- @Override
- public boolean contains(GCookie.Key key) {
- return get(key) != null;
- }
-
- @Override
- @Nullable
- public GCookie get(GCookie.Key key) {
- Preconditions.checkNotNull(key);
- return map.get(key);
- }
-}
diff --git a/src/com/google/enterprise/secmgr/common/FileUtil.java b/src/com/google/enterprise/secmgr/common/FileUtil.java
deleted file mode 100644
index 56ed934..0000000
--- a/src/com/google/enterprise/secmgr/common/FileUtil.java
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright 2008 Google Inc.
-//
-// 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.google.enterprise.secmgr.common;
-
-import com.google.common.base.Preconditions;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * Utilities for finding files.
- */
-public class FileUtil {
-
- private static String contextDirectory;
- private static String commonDirectory;
-
- private static final String GOOGLE3_TEST_UTIL_CLASS = "com.google.testing.util.TestUtil";
- private static final String GET_SRC_DIR_METHOD = "getSrcDir";
- private static final String GET_TMP_DIR_METHOD = "getTmpDir";
- private static final String GOOGLE3_TESTDATA_ROOT =
- "/google3/javatests/com/google/enterprise/secmgr/testdata";
- private static final String NON_GOOGLE3_TESTDATA_ROOT = "testdata/mocktestdata/";
-
- private static final String BEGIN_PEM_CERTIFICATE_MARKER = "-----BEGIN CERTIFICATE-----";
- private static final String END_PEM_CERTIFICATE_MARKER = "-----END CERTIFICATE-----";
-
- // don't instantiate
- private FileUtil() {
- }
-
- /**
- * Initialize the context and common directories for testing. Chooses appropriate
- * values for them depending on the testing context.
- */
- public static void initializeTestDirectories() {
- Class<?> clazz;
- try {
- clazz = Class.forName(GOOGLE3_TEST_UTIL_CLASS);
- } catch (ClassNotFoundException e) {
- // no worries -- this just means we're not in a google3 environment
- contextDirectory = NON_GOOGLE3_TESTDATA_ROOT;
- commonDirectory = NON_GOOGLE3_TESTDATA_ROOT;
- return;
- }
-
- Method m1;
- Method m2;
- try {
- m1 = clazz.getDeclaredMethod(GET_SRC_DIR_METHOD);
- m2 = clazz.getDeclaredMethod(GET_TMP_DIR_METHOD);
- } catch (NoSuchMethodException e) {
- throw new IllegalStateException(e);
- }
-
- String srcDir;
- String tmpDir;
- try {
- srcDir = String.class.cast(m1.invoke(null));
- tmpDir = String.class.cast(m2.invoke(null));
- } catch (IllegalAccessException e) {
- throw new IllegalStateException(e);
- } catch (InvocationTargetException e) {
- throw new IllegalStateException(e);
- }
-
- contextDirectory = srcDir + GOOGLE3_TESTDATA_ROOT;
- commonDirectory = tmpDir;
- }
-
- /**
- * Get the context directory. This directory holds the config files used by
- * the security manager.
- *
- * @return The context directory as a string.
- */
- public static String getContextDirectory() {
- return contextDirectory;
- }
-
- /**
- * Get the common directory. This directory holds all persistent state maintained by
- * the connector manager.
- *
- * @return The common directory as a string.
- */
- public static String getCommonDirectory() {
- // Allow override via command-line flags so that large tests can easily
- // specify a tmp directory.
- String testTmpDir = System.getProperty("google3.tmpdir");
- if (testTmpDir != null) {
- return testTmpDir;
- }
- return commonDirectory;
- }
-
- /**
- * Set the Context/Common directory. To be called only from the servlet
- * initialization in a production environment.
- */
- public static void setContextDirectory(String directory) {
- contextDirectory = directory;
- commonDirectory = directory;
- }
-
- /**
- * Resolve relative filenames in the directory of the config files.
- *
- * @param filename A (potentially relative) filename.
- * @return An absolute File object.
- */
- public static File getContextFile(String filename) {
- Preconditions.checkNotNull(filename);
- return getContextFile(new File(filename));
- }
-
- /**
- * Resolve relative filenames in the directory of the config files.
- *
- * @param file A (potentially relative) File object.
- * @return An absolute File object.
- */
- public static File getContextFile(File file) {
- Preconditions.checkNotNull(file);
- return (file.isAbsolute()) ? file : new File(getContextDirectory(), file.toString());
- }
-
- /**
- * Resolve relative filenames in the common directory.
- *
- * @param filename A (potentially relative) filename.
- * @return An absolute File object.
- * @see #getCommonDirectory
- */
- public static File getCommonFile(String filename) {
- Preconditions.checkNotNull(filename);
- return getCommonFile(new File(filename));
- }
-
- /**
- * Resolve relative filenames in the common directory.
- *
- * @param file A (potentially relative) File object.
- * @return An absolute File object.
- * @see #getCommonDirectory
- */
- public static File getCommonFile(File file) {
- Preconditions.checkNotNull(file);
- return (file.isAbsolute()) ? file : new File(getCommonDirectory(), file.toString());
- }
-
- /**
- * Read a file's contents and return them as a string.
- *
- * @param file The file to read.
- * @return The file's contents.
- * @throws IOException if unable to read the file.
- */
- public static String readFile(File file)
- throws IOException {
- Preconditions.checkNotNull(file);
- StringBuffer accumulator = new StringBuffer();
- char[] buffer = new char[4096];
- Reader reader = null;
- try {
- reader = new FileReader(file);
- while (true) {
- int nRead = reader.read(buffer);
- if (nRead < 0) {
- break;
- }
- accumulator.append(buffer, 0, nRead);
- }
- } finally {
- if (reader != null) {
- reader.close();
- }
- }
- return accumulator.toString();
- }
-
- /**
- * Read a PEM-encoded certificate file and return the Base64 part as a string.
- *
- * @param file The file to read.
- * @return The certificate in Base64 encoding.
- * @throws IOException if unable to read or parse the file.
- */
- public static String readPEMCertificateFile(File file)
- throws IOException {
- String certFile = readFile(file);
- int start = certFile.indexOf(BEGIN_PEM_CERTIFICATE_MARKER);
- if (start < 0) {
- throw new IOException("Certificate file missing begin marker");
- }
- start += BEGIN_PEM_CERTIFICATE_MARKER.length();
- int end = certFile.indexOf(END_PEM_CERTIFICATE_MARKER, start);
- if (end < 0) {
- throw new IOException("Certificate file missing end marker");
- }
- return certFile.substring(start, end - 1);
- }
-}
diff --git a/src/com/google/enterprise/secmgr/common/GCookie.java b/src/com/google/enterprise/secmgr/common/GCookie.java
deleted file mode 100644
index cd638ae..0000000
--- a/src/com/google/enterprise/secmgr/common/GCookie.java
+++ /dev/null
@@ -1,1873 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.google.enterprise.secmgr.common;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.CharMatcher;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-
-import org.joda.time.DateTimeUtils;
-
-import java.net.URI;
-import java.util.Calendar;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.logging.Logger;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnegative;
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-import javax.annotation.concurrent.NotThreadSafe;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * An immutable cookie implementation that complies with RFC 6265. Note that
- * this implementation does not (yet) support IDNA (RFC 5890) even though that
- * is required by the specification.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class GCookie {
- private static final Logger LOGGER = Logger.getLogger(GCookie.class.getName());
-
- // A cookie with its name in this list will always have its value logged in
- // cleartext.
- private static final ImmutableList<String> ALWAYS_SHOW_VALUE =
- ImmutableList.of("GSA_SESSION_ID", "JSESSIONID");
- private static final char OBFUSCATED_VALUE_PREFIX = '#';
- private static final char VALUE_SEPARATOR = '=';
- private static final char REQUEST_SEPARATOR = ';';
- private static final String REQUEST_SEPARATOR_STRING = "; ";
- private static final char ATTR_SEPARATOR = ';';
- private static final String ATTR_SEPARATOR_STRING = "; ";
- private static final char PATH_SEPARATOR = '/';
- public static final String UNIVERSAL_PATH = "/";
-
- private static final CharMatcher WSP = CharMatcher.anyOf(" \t");
-
- /**
- * Characters allowed in a cookie name. Servers are supposed to restrict
- * names to the HTTP token syntax.
- */
- private static final CharMatcher COOKIE_NAME = CharMatcher.noneOf(";=");
-
- /**
- * Characters allowed in a cookie value. Servers are supposed to restrict
- * values to octets between 0x21 and 0x7E inclusive, except for {@code '"'},
- * {@code '\\'}, {@code ','}, and {@code ';'}. The value may optionally be
- * surrounded by double quotes.
- */
- private static final CharMatcher COOKIE_VALUE = CharMatcher.noneOf(";");
-
- /**
- * Cookies are distinguished by their name, their domain, and their path. If
- * two cookies have the same values for those elements, they are considered to
- * be the same cookie. This class formalizes that concept by providing an
- * object representing the distinguishing components.
- */
- @Immutable
- @ParametersAreNonnullByDefault
- public static final class Key {
- @Nonnull private final String name;
- @Nonnull private final String domain;
- @Nonnull private final String path;
-
- private Key(String name, String domain, String path) {
- this.name = name;
- this.domain = domain;
- this.path = path;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof Key)) { return false; }
- Key other = (Key) object;
- return getName().equalsIgnoreCase(other.getName())
- && getDomain().equalsIgnoreCase(other.getDomain())
- && getPath().equals(other.getPath());
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(name.toLowerCase(Locale.US), domain.toLowerCase(Locale.US), path);
- }
-
- // True only of cookies that didn't come from a set-cookie header.
- boolean isPartial() {
- return domain.isEmpty() && path.isEmpty();
- }
-
- /**
- * Gets the name for this key.
- *
- * @return This key's name.
- */
- @CheckReturnValue
- @Nonnull
- public String getName() {
- return name;
- }
-
- /**
- * Gets the domain for this key.
- *
- * @return This key's domain.
- */
- @CheckReturnValue
- @Nonnull
- public String getDomain() {
- return domain;
- }
-
- /**
- * Gets the path for this key.
- *
- * @return This key's path.
- */
- @CheckReturnValue
- @Nonnull
- public String getPath() {
- return path;
- }
- }
-
- @Nonnull private final Key key;
- @Nonnull private final String value;
- @Nonnegative private final long expires;
- @Nonnegative private final long creationTime;
- @Nonnegative private final long lastAccessTime;
- private final boolean persistent;
- private final boolean hostOnly;
- private final boolean secureOnly;
- private final boolean httpOnly;
-
- private GCookie(Key key, String value, @Nonnegative long expires, @Nonnegative long creationTime,
- @Nonnegative long lastAccessTime, boolean persistent, boolean hostOnly, boolean secureOnly,
- boolean httpOnly) {
- this.key = key;
- this.value = value;
- this.expires = expires;
- this.creationTime = creationTime;
- this.lastAccessTime = lastAccessTime;
- this.persistent = persistent;
- this.hostOnly = hostOnly;
- this.secureOnly = secureOnly;
- this.httpOnly = httpOnly;
- }
-
- // **************** Accessors ****************
-
- /**
- * Gets the cookie's key, an object that embodies what it means for two
- * cookies to have the "same name".
- *
- * @return The key.
- */
- @CheckReturnValue
- @Nonnull
- public Key getKey() {
- return key;
- }
-
- /**
- * Gets the cookie's name, which is a non-empty case-insensitve string.
- *
- * @return The name.
- */
- @CheckReturnValue
- @Nonnull
- public String getName() {
- return key.getName();
- }
-
- /**
- * Gets the cookie's value.
- *
- * @return The value.
- */
- @CheckReturnValue
- @Nonnull
- public String getValue() {
- return value;
- }
-
- /**
- * Gets the cookie's expiration time in milliseconds from the epoch.
- *
- * @return The expiration time.
- */
- @CheckReturnValue
- @Nonnegative
- public long getExpires() {
- return expires;
- }
-
- /**
- * Gets the cookie's domain.
- *
- * @return The domain.
- */
- @CheckReturnValue
- @Nonnull
- public String getDomain() {
- return key.getDomain();
- }
-
- /**
- * Gets the cookie's path.
- *
- * @return The path.
- */
- @CheckReturnValue
- @Nonnull
- public String getPath() {
- return key.getPath();
- }
-
- /**
- * Gets the cookie's creation time in milliseconds from the epoch.
- *
- * @return The creation time.
- */
- @CheckReturnValue
- @Nonnegative
- public long getCreationTime() {
- return creationTime;
- }
-
- /**
- * Gets the cookie's last-access time in milliseconds from the epoch.
- *
- * @return The last-access time.
- */
- @CheckReturnValue
- @Nonnegative
- public long getLastAccessTime() {
- return lastAccessTime;
- }
-
- /**
- * Is the cookie persistent?
- *
- * @return True if the cookie is persistent.
- */
- @CheckReturnValue
- public boolean getPersistent() {
- return persistent;
- }
-
- /**
- * Should this cookie be restricted to the host that exactly matches its domain?
- *
- * @return True if the cookie should be restricted.
- */
- @CheckReturnValue
- public boolean getHostOnly() {
- return hostOnly;
- }
-
- /**
- * Is the cookie valid only for "secure" connections?
- *
- * @return True if the cookie is usable only for HTTPS and other secure
- * connections.
- */
- @CheckReturnValue
- public boolean getSecureOnly() {
- return secureOnly;
- }
-
- /**
- * Should the cookie be restricted to HTTP messages? If true, Javascript
- * client programs can't access this cookie.
- *
- * @return True if the cookie should be restricted.
- */
- @CheckReturnValue
- public boolean getHttpOnly() {
- return httpOnly;
- }
-
- /**
- * Is this cookie expired?
- *
- * @param timeStamp The reference time at which to determine the answer.
- * @return True if the cookie is expired.
- */
- @CheckReturnValue
- public boolean isExpired(@Nonnegative long timeStamp) {
- Preconditions.checkArgument(timeStamp >= 0);
- return getExpires() <= timeStamp;
- }
-
- /**
- * Gets a predicate that computes {@link #isExpired}.
- *
- * @param timeStamp The reference time at which to determine the answer.
- * @return A predicate that's true if a given cookie is expired at the
- * reference time.
- */
- @CheckReturnValue
- @Nonnull
- public static Predicate<GCookie> isExpiredPredicate(@Nonnegative final long timeStamp) {
- Preconditions.checkArgument(timeStamp >= 0);
- return new Predicate<GCookie>() {
- @Override
- public boolean apply(GCookie cookie) {
- return cookie.getExpires() <= timeStamp;
- }
- };
- }
-
- /**
- * Gets the "maximum age" of this cookie. Normally this isn't used; it's provided
- * for compatibility. Instead use {@link #getExpires}.
- *
- * @return The "maximum age" of this cookie in seconds, or {@code -1} for a
- * session cookie.
- */
- @CheckReturnValue
- public int getMaxAge() {
- if (!getPersistent()) {
- return -1;
- }
- if (getExpires() < getCreationTime()) {
- return 0;
- }
- long deltaSeconds = ((getExpires() - getCreationTime()) + 500) / 1000;
- return (deltaSeconds > Integer.MAX_VALUE)
- ? -1
- : (int) deltaSeconds;
- }
-
- // **************** Equality ****************
-
- /** Note that equality doesn't consider any of the cookie's times. */
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof GCookie)) { return false; }
- GCookie other = (GCookie) object;
- return getKey().equals(other.getKey())
- && getValue().equals(other.getValue())
- && getPersistent() == other.getPersistent()
- && getSecureOnly() == other.getSecureOnly()
- && getHttpOnly() == other.getHttpOnly();
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(getKey(), getValue(), getPersistent(), getSecureOnly(), getHttpOnly());
- }
-
- /**
- * Checks whether a given cookie has the same name as this cookie.
- *
- * @param cookie The cookie to compare against.
- * @return True only if the names match.
- */
- @CheckReturnValue
- public boolean hasSameName(GCookie cookie) {
- return getName().equalsIgnoreCase(cookie.getName());
- }
-
- /**
- * Checks whether any of some given cookies have the same name as this cookie.
- *
- * @param cookies The cookies to compare against.
- * @return True only if the name of one of the cookies matches.
- */
- @CheckReturnValue
- public boolean hasSameName(Iterable<GCookie> cookies) {
- for (GCookie cookie : cookies) {
- if (hasSameName(cookie)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks whether a given cookie has the same key as this cookie.
- *
- * @param cookie The cookie to compare against.
- * @return True only if the keys match.
- */
- @CheckReturnValue
- public boolean hasSameKey(GCookie cookie) {
- return getKey().equals(cookie.getKey());
- }
-
- /**
- * Checks whether any of some given cookies have the same key as this cookie.
- *
- * @param cookies The cookies to compare against.
- * @return True only if the key of one of the cookies matches.
- */
- @CheckReturnValue
- public boolean hasSameKey(Iterable<GCookie> cookies) {
- for (GCookie cookie : cookies) {
- if (hasSameKey(cookie)) {
- return true;
- }
- }
- return false;
- }
-
- // **************** Logging support ****************
-
- @Override
- public String toString() {
- return responseHeaderString(false);
- }
-
- /**
- * Generates a log message containing a description of some given cookies in
- * request format.
- *
- * @param prefix A prefix for the log message.
- * @param cookies The cookies to be described.
- * @return A suitably formatted log message.
- */
- @CheckReturnValue
- @Nonnull
- public static String requestCookiesMessage(String prefix, Iterable<GCookie> cookies) {
- StringBuilder builder = new StringBuilder();
- builder.append(prefix);
- builder.append(": ");
- if (Iterables.isEmpty(cookies)) {
- builder.append("(none)");
- } else {
- writeRequest(cookies, false, builder);
- }
- return builder.toString();
- }
-
- /**
- * Generates a log message containing a description of some given cookies in
- * response format.
- *
- * @param prefix A prefix for the log message.
- * @param cookies The cookies to be described.
- * @return A suitably formatted log message.
- */
- @CheckReturnValue
- @Nonnull
- public static String responseCookiesMessage(String prefix, Iterable<GCookie> cookies) {
- StringBuilder builder = new StringBuilder();
- builder.append(prefix);
- builder.append(": ");
- if (Iterables.isEmpty(cookies)) {
- builder.append("(none)");
- } else {
- boolean needSeparator = false;
- for (GCookie cookie : cookies) {
- if (needSeparator) {
- builder.append(", ");
- } else {
- needSeparator = true;
- }
- cookie.writeResponse(false, builder);
- }
- }
- return builder.toString();
- }
-
- // **************** URI filtering ****************
-
- /**
- * Checks if this cookie is suitable for a given target URI.
- *
- * @param uri The URI object to test against.
- * @return True if the cookie is suitable to be sent to the URI.
- */
- @CheckReturnValue
- public boolean isGoodFor(URI uri) {
- return domainMatch(getDomain(), getHostOnly(), computeRequestHost(uri))
- && pathMatch(getPath(), uri.getPath())
- && secureOnlyMatch(getSecureOnly(), uri.getScheme());
- }
-
- private static boolean domainMatch(String cookieDomain, boolean hostOnly, String requestHost) {
- if (cookieDomain.isEmpty()) {
- return true;
- }
- requestHost = requestHost.toLowerCase(Locale.US);
- if (requestHost.equals(cookieDomain)) {
- return true;
- }
- if (hostOnly) {
- return false;
- }
- return requestHost.endsWith(cookieDomain)
- && requestHost.charAt(requestHost.length() - cookieDomain.length() - 1) == '.';
- }
-
- private static boolean pathMatch(String cookiePath, String requestPath) {
- return cookiePath.isEmpty()
- || requestPath.equals(cookiePath)
- || (requestPath.startsWith(cookiePath)
- && (lastChar(cookiePath) == PATH_SEPARATOR
- || requestPath.charAt(cookiePath.length()) == PATH_SEPARATOR));
- }
-
- private static char firstChar(String string) {
- return string.charAt(0);
- }
-
- private static char lastChar(String string) {
- return string.charAt(string.length() - 1);
- }
-
- private static boolean secureOnlyMatch(boolean secureOnly, String requestProtocol) {
- return !secureOnly || "https".equalsIgnoreCase(requestProtocol);
- }
-
- /**
- * Determine whether there are any cookies to send.
- *
- * @param uri The URI of the authority.
- * @param userAgentCookies The cookies received from the user agent.
- * @param authorityCookies The cookies previously received from the authority.
- * @return True if there are some cookies to be sent.
- */
- @CheckReturnValue
- public static boolean haveCookiesToSend(URI uri, Iterable<GCookie> userAgentCookies,
- Iterable<GCookie> authorityCookies) {
- return anyCookieGoodFor(userAgentCookies, uri)
- || anyCookieGoodFor(authorityCookies, uri);
- }
-
- private static boolean anyCookieGoodFor(Iterable<GCookie> cookies, URI uri) {
- for (GCookie cookie : cookies) {
- if (cookie.isGoodFor(uri)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Compute the cookies to send to a given authority. Authority cookies have
- * priority over user-agent cookies.
- *
- * @param uri The URI of the authority.
- * @param userAgentCookies The cookies received from the user agent.
- * @param authorityCookies The cookies previously received from the authority.
- * @param store The cookie store to add the "to-send" cookies to.
- */
- public static void computeCookiesToSend(URI uri, Iterable<GCookie> userAgentCookies,
- Iterable<GCookie> authorityCookies, CookieStore store) {
- for (GCookie cookie : authorityCookies) {
- if (cookie.isGoodFor(uri)) {
- store.add(cookie);
- }
- }
- for (GCookie cookie : userAgentCookies) {
- if (cookie.isGoodFor(uri) && !store.contains(cookie.getName())) {
- store.add(cookie);
- }
- }
- }
-
- /**
- * Compute the cookies to send to a given authority. Authority cookies have
- * priority over user-agent cookies.
- *
- * @param uri The URI of the authority.
- * @param userAgentCookies The cookies received from the user agent.
- * @param authorityCookies The cookies previously received from the authority.
- * @return A cookie store containing the "to-send" cookies.
- */
- @CheckReturnValue
- @Nonnull
- public static CookieStore computeCookiesToSend(URI uri,
- Iterable<GCookie> userAgentCookies, Iterable<GCookie> authorityCookies) {
- CookieStore store = makeStore();
- computeCookiesToSend(uri, userAgentCookies, authorityCookies, store);
- store.expireCookies();
- return store;
- }
-
- // **************** Cookie store ****************
-
- /**
- * Makes a new empty store.
- *
- * @return A new empty store.
- */
- @CheckReturnValue
- @Nonnull
- public static CookieStore makeStore() {
- return new CookieStoreImpl();
- }
-
- /**
- * Makes a new store and adds some cookies to it.
- *
- * @param cookies The cookies to be added.
- * @return A new store containing the given cookies.
- */
- @CheckReturnValue
- @Nonnull
- public static CookieStore makeStore(Iterable<GCookie> cookies) {
- CookieStore store = makeStore();
- Iterables.addAll(store, cookies);
- store.expireCookies();
- return store;
- }
-
- /**
- * Merge two collections of cookies together.
- *
- * @param cookies1 The first collection.
- * @param cookies2 The second collection, which overrides the first.
- * @return The merged collection.
- */
- @CheckReturnValue
- @Nonnull
- public static Iterable<GCookie> mergeCookies(Iterable<GCookie> cookies1,
- Iterable<GCookie> cookies2) {
- CookieStore store = makeStore();
- Iterables.addAll(store, cookies1);
- Iterables.addAll(store, cookies2);
- store.expireCookies();
- return store;
- }
-
- // **************** Conversions to/from Java cookies ****************
-
- /**
- * Converts a cookie to a {@link GCookie}.
- *
- * @param cookie A cookie to be converted.
- * @return The converted cookie.
- */
- @CheckReturnValue
- @Nonnull
- public static GCookie fromCookie(Cookie cookie) {
- return builder(cookie).build();
- }
-
- /**
- * Converts this {@link GCookie} to a {@link Cookie}.
- *
- * @return A newly created {@link Cookie}.
- * @throws RuntimeException if unable to perform the conversion.
- */
- @CheckReturnValue
- @Nonnull
- public Cookie toCookie() {
- Cookie cookie = new Cookie(getName(), getValue());
- cookie.setValue(getValue());
- if (getDomain() != null) {
- cookie.setDomain(getDomain());
- }
- cookie.setPath(getPath());
- cookie.setSecure(getSecureOnly());
- cookie.setMaxAge(getMaxAge());
- return cookie;
- }
-
- /**
- * Converts some {@link GCookie}s to {@link Cookie}s.
- *
- * @param cookies The cookies to be converted.
- * @return The converted cookies, except for those that fail to convert.
- */
- @CheckReturnValue
- @Nonnull
- public static ImmutableList<Cookie> toCookie(Iterable<GCookie> cookies) {
- ImmutableList.Builder<Cookie> builder = ImmutableList.builder();
- for (GCookie cookie : cookies) {
- Cookie c;
- try {
- c = cookie.toCookie();
- } catch (RuntimeException e) {
- continue;
- }
- builder.add(c);
- }
- return builder.build();
- }
-
- // **************** Generating HTTP headers ****************
-
- /**
- * Gets a string representing the given cookies in request format.
- *
- * @param cookies The cookies to convert.
- * @param showValues If false, the cookie's value will be obfuscated in the
- * returned string.
- * @return The formatted string.
- */
- @CheckReturnValue
- @Nonnull
- public static String requestHeaderString(Iterable<GCookie> cookies,
- boolean showValues) {
- StringBuilder builder = new StringBuilder();
- writeRequest(cookies, showValues, builder);
- return builder.toString();
- }
-
- /**
- * Writes a representation of the given cookies in request format.
- *
- * @param cookies The cookies to write.
- * @param showValues If false, the cookie's value will be obfuscated in the
- * returned string.
- * @param builder A string builder to write the representation to.
- */
- public static void writeRequest(Iterable<GCookie> cookies, boolean showValues,
- StringBuilder builder) {
- boolean needSeparator = false;
- for (GCookie cookie : cookies) {
- if (needSeparator) {
- builder.append(REQUEST_SEPARATOR_STRING);
- } else {
- needSeparator = true;
- }
- cookie.writeRequest(showValues, builder);
- }
- }
-
- /**
- * Gets a string representing this cookie in request format.
- *
- * @param showValues If false, the cookie's value will be obfuscated in the
- * returned string.
- * @return The formatted string.
- */
- @CheckReturnValue
- @Nonnull
- public String requestHeaderString(boolean showValues) {
- StringBuilder builder = new StringBuilder();
- writeRequest(showValues, builder);
- return builder.toString();
- }
-
- /**
- * Writes a representation of this cookie in request format.
- *
- * @param showValues If false, the cookie's value will be obfuscated in the
- * returned string.
- * @param builder A string builder to write the representation to.
- */
- public void writeRequest(boolean showValues, StringBuilder builder) {
- writeBinding(showValues, builder);
- }
-
- /**
- * Gets a string representing this cookie in response format.
- *
- * @param showValues If false, the cookie's value will be obfuscated in the
- * returned string.
- * @return The formatted string.
- */
- @CheckReturnValue
- @Nonnull
- public String responseHeaderString(boolean showValues) {
- StringBuilder builder = new StringBuilder();
- writeResponse(showValues, builder);
- return builder.toString();
- }
-
- /**
- * Writes a representation of this cookie in response format.
- *
- * @param showValues If false, the cookie's value will be obfuscated in the
- * returned string.
- * @param builder A string builder to write the representation to.
- */
- public void writeResponse(boolean showValues, StringBuilder builder) {
- writeBinding(showValues, builder);
- if (getExpires() < Long.MAX_VALUE) {
- writeAttr(AttrName.EXPIRES, HttpUtil.generateHttpDate(getExpires()), builder);
- }
- writeAttr(AttrName.MAX_AGE, getMaxAge(), builder);
- if (!(getHostOnly() || getDomain().isEmpty())) {
- String domain = getDomain();
- if (!domain.startsWith(".")) {
- domain = "." + domain;
- }
- writeAttr(AttrName.DOMAIN, domain, builder);
- }
- writeAttr(AttrName.PATH, getPath(), builder);
- writeAttr(AttrName.SECURE, getSecureOnly(), builder);
- writeAttr(AttrName.HTTP_ONLY, getHttpOnly(), builder);
- }
-
- private void writeBinding(boolean showValues, StringBuilder builder) {
- builder.append(getName());
- builder.append(VALUE_SEPARATOR);
- if (!getValue().isEmpty()) {
- if (showValues || alwaysShowValue(getName())) {
- builder.append(getValue());
- } else {
- builder.append(OBFUSCATED_VALUE_PREFIX);
- builder.append(
- Base64.encodeWebSafe(SecurePasswordHasher.macInput(getName(), getValue()), false));
- }
- }
- }
-
- private static void writeAttr(AttrName param, String value, StringBuilder builder) {
- if (!value.isEmpty()) {
- builder.append(ATTR_SEPARATOR_STRING);
- builder.append(param.toString());
- builder.append(VALUE_SEPARATOR);
- builder.append(value);
- }
- }
-
- private static void writeAttr(AttrName param, int value, StringBuilder builder) {
- if (value >= 0) {
- writeAttr(param, Integer.toString(value), builder);
- }
- }
-
- private static void writeAttr(AttrName param, boolean value, StringBuilder builder) {
- if (value) {
- builder.append(ATTR_SEPARATOR_STRING);
- builder.append(param.toString());
- }
- }
-
- private static boolean alwaysShowValue(String name) {
- for (String name2 : ALWAYS_SHOW_VALUE) {
- if (name2.equalsIgnoreCase(name)) {
- return true;
- }
- }
- return false;
- }
-
- private enum AttrName {
- EXPIRES("Expires"),
- MAX_AGE("Max-Age"),
- DOMAIN("Domain"),
- PATH("Path"),
- SECURE("Secure"),
- HTTP_ONLY("HttpOnly");
-
- @Nonnull private final String name;
-
- private AttrName(String name) {
- this.name = name;
- }
-
- @Override
- public String toString() {
- return name;
- }
- }
-
- // **************** Parsers ****************
-
- /**
- * Parses request header values to produce cookies. Returns Java cookies for
- * use by legacy code.
- *
- * @param headers The header values to parse.
- * @return An immutable list of the parsed cookies.
- */
- @CheckReturnValue
- @Nonnull
- public static ImmutableList<Cookie> legacyParseRequestHeaders(Iterable<String> headers) {
- CookieStore store = makeStore();
- parseRequestHeaders(headers, null, null, store);
- return toCookie(store);
- }
-
- /**
- * Parses request header values to produce cookies.
- *
- * @param headers The header values to parse.
- * @param requestUri The request URI.
- * @param sessionId A session ID to add to log messages.
- * @param store A cookie store to which the parsed cookies will be added.
- */
- public static void parseRequestHeaders(Iterable<String> headers, URI requestUri, String sessionId,
- CookieStore store) {
- long now = DateTimeUtils.currentTimeMillis();
- for (String header : headers) {
- for (String cookiePair : REQUEST_SPLITTER.split(header)) {
- Builder builder;
- try {
- builder = parseCookiePair(cookiePair, now);
- } catch (ParseException e) {
- LOGGER.info(SecurityManagerUtil.sessionLogMessage(sessionId, e.getMessage()));
- continue;
- }
- store.add(builder.build());
- }
- }
- store.expireCookies(now);
- }
-
- /**
- * Parses response header values to produce cookies.
- *
- * @param headers The header values to parse.
- * @param requestUri The request URI corresponding to this response.
- * @param sessionId A session ID to add to log messages.
- * @param store A cookie store to which the parsed cookies will be added.
- */
- public static void parseResponseHeaders(Iterable<String> headers, URI requestUri,
- String sessionId, CookieStore store) {
- long now = DateTimeUtils.currentTimeMillis();
- for (String header : headers) {
- GCookie cookie;
- try {
- cookie = parseResponseHeader(header, requestUri, now);
- } catch (ParseException e) {
- LOGGER.info(SecurityManagerUtil.sessionLogMessage(sessionId, e.getMessage()));
- continue;
- }
- store.add(cookie);
- }
- store.expireCookies(now);
- }
-
- private static GCookie parseResponseHeader(String header, URI requestUri, long now)
- throws ParseException {
- List<String> parts = ImmutableList.copyOf(ATTR_SPLITTER.split(header));
- if (parts.isEmpty()) {
- parseError("No value separator in: %s", Stringify.object(header));
- }
- Builder builder = parseCookiePair(parts.get(0), now)
- .setCreationTime(now)
- .setLastAccessTime(now);
- Map<AttrName, Object> parsedAttrs = parseAttrs(parts.subList(1, parts.size()));
-
- Long maxAgeRaw = Long.class.cast(parsedAttrs.get(AttrName.MAX_AGE));
- if (maxAgeRaw != null) {
- long maxAge = maxAgeRaw.longValue();
- long expires;
- if (maxAge <= 0) {
- expires = 0;
- } else {
- expires = now + maxAge;
- if (expires < 0) {
- // Means we got an overflow.
- expires = Long.MAX_VALUE;
- }
- }
- builder.setPersistent(true);
- builder.setExpires(expires);
- } else {
- Long expiresRaw = Long.class.cast(parsedAttrs.get(AttrName.EXPIRES));
- if (expiresRaw != null) {
- long expires = expiresRaw.longValue();
- if (expires >= 0) {
- builder.setPersistent(true);
- builder.setExpires(expires);
- } else {
- builder.setPersistent(false);
- builder.setExpires(Long.MAX_VALUE);
- }
- }
- }
-
- if (requestUri != null) {
- String requestHost = computeRequestHost(requestUri);
- String domain = String.class.cast(parsedAttrs.get(AttrName.DOMAIN));
- if (domain == null) {
- domain = "";
- }
- if (isPublicSuffix(domain)) {
- if (!domain.equals(requestHost)) {
- parseError("Cookie domain %s is a public domain",
- Stringify.object(domain));
- }
- domain = "";
- }
- if (domain.isEmpty()) {
- builder.setHostOnly(true);
- builder.setDomain(requestHost);
- } else {
- if (!domainMatch(domain, false, requestHost)) {
- parseError("Cookie domain %s doesn't match request host %s",
- Stringify.object(domain), Stringify.object(requestHost));
- }
- builder.setHostOnly(false);
- builder.setDomain(domain);
- }
-
- String path = String.class.cast(parsedAttrs.get(AttrName.PATH));
- if (path == null || path.isEmpty()) {
- builder.setPath(computeDefaultPath(requestUri));
- } else {
- builder.setPath(path);
- }
- }
-
- builder.setSecureOnly(parsedAttrs.get(AttrName.SECURE) != null);
- builder.setHttpOnly(parsedAttrs.get(AttrName.HTTP_ONLY) != null);
-
- return builder.build();
- }
-
- private static Builder parseCookiePair(String cookiePair, long now)
- throws ParseException {
- int vsep = cookiePair.indexOf(VALUE_SEPARATOR);
- if (vsep < 0) {
- parseError("No value separator in: %s",
- Stringify.object(cookiePair));
- }
- String name = WSP.trimFrom(cookiePair.substring(0, vsep));
- if (!isCookieName(name)) {
- parseError("Invalid cookie name %s in: %s",
- Stringify.object(name), Stringify.object(cookiePair));
- }
- String value = WSP.trimFrom(cookiePair.substring(vsep + 1));
- if (!isCookieValue(value)) {
- parseError("Invalid cookie value %s in: %s",
- Stringify.object(value), Stringify.object(cookiePair));
- }
- return builder(name, now).setValue(value);
- }
-
- private static final Splitter REQUEST_SPLITTER =
- Splitter.on(REQUEST_SEPARATOR).trimResults().omitEmptyStrings();
-
- private static final Splitter ATTR_SPLITTER =
- Splitter.on(ATTR_SEPARATOR).trimResults().omitEmptyStrings();
-
- private static Map<AttrName, Object> parseAttrs(List<String> unparsedAttrs) {
- Map<AttrName, Object> parsedAttrs = Maps.newHashMap();
- for (String unparsed : unparsedAttrs) {
- String aname;
- String avalue;
- int vsep = unparsed.indexOf(VALUE_SEPARATOR);
- if (vsep < 0) {
- aname = WSP.trimFrom(unparsed);
- avalue = "";
- } else {
- aname = WSP.trimFrom(unparsed.substring(0, vsep));
- avalue = WSP.trimFrom(unparsed.substring(vsep + 1));
- }
- AttrName attrName = findAttrName(aname);
- if (attrName != null) {
- Object value = dispatchAttr(attrName, avalue);
- if (value != null) {
- parsedAttrs.put(attrName, value);
- }
- }
- }
- return parsedAttrs;
- }
-
- private static AttrName findAttrName(String aname) {
- for (AttrName attrName : EnumSet.allOf(AttrName.class)) {
- if (attrName.toString().equalsIgnoreCase(aname)) {
- return attrName;
- }
- }
- return null;
- }
-
- private static Object dispatchAttr(AttrName attrName, String avalue) {
- switch (attrName) {
- case EXPIRES: return parseExpires(avalue);
- case MAX_AGE: return parseMaxAge(avalue);
- case DOMAIN: return parseDomain(avalue);
- case PATH: return parsePath(avalue);
- case SECURE: return parseSecure(avalue);
- case HTTP_ONLY: return parseHttpOnly(avalue);
- default: throw new IllegalStateException("Unknown AttrName: " + attrName);
- }
- }
-
- private static Long parseExpires(String expires) {
- try {
- return parseDate(expires);
- } catch (IllegalArgumentException e) {
- LOGGER.info("Error parsing Expires attribute: " + e.getMessage());
- return null;
- }
- }
-
- private static Long parseMaxAge(String maxAge) {
- try {
- return Long.parseLong(maxAge);
- } catch (NumberFormatException e) {
- return null;
- }
- }
-
- private static String parseDomain(String domain) {
- return domain.isEmpty() ? null : canonicalizeDomain(domain);
- }
-
- private static String canonicalizeDomain(String domain) {
- if (domain.startsWith(".")) {
- domain = domain.substring(1);
- }
- try {
- // Do full canonicalization if possible.
- return HttpUtil.canonicalizeDomainName(domain);
- } catch (IllegalArgumentException e) {
- // Otherwise fall back to simple case folding.
- return domain.toLowerCase(Locale.US);
- }
- }
-
- private static boolean isPublicSuffix(String domain) {
- // TODO(cph): should check for "public suffix" here. See
- // <http://publicsuffix.org/>.
- return false;
- }
-
- private static String parsePath(String path) {
- return (path.isEmpty() || firstChar(path) != PATH_SEPARATOR)
- ? ""
- : path;
- }
-
- private static boolean parseSecure(String avalue) {
- return true;
- }
-
- private static boolean parseHttpOnly(String avalue) {
- return true;
- }
-
- private static String computeRequestHost(URI requestUri) {
- String host = requestUri.getHost();
- try {
- return HttpUtil.canonicalizeDomainName(host);
- } catch (IllegalArgumentException e) {
- return host.toLowerCase(Locale.US);
- }
- }
-
- private static String computeDefaultPath(URI requestUri) {
- String path = requestUri.getPath();
- if (path.isEmpty() || firstChar(path) != PATH_SEPARATOR) {
- return UNIVERSAL_PATH;
- }
- int lastSeparator = path.lastIndexOf(PATH_SEPARATOR);
- return (lastSeparator > 0)
- ? path.substring(0, lastSeparator)
- : UNIVERSAL_PATH;
- }
-
- private static String parseError(String format, Object... args)
- throws ParseException {
- throw new ParseException(String.format(format, args));
- }
-
- /**
- * An exception that's thrown by a cookie parser when the input can't be
- * parsed.
- */
- public static final class ParseException extends Exception {
- ParseException(String message) { super(message); }
- }
-
- // **************** Element predicates and canonicalizers ****************
-
- /**
- * Is the given string a valid cookie name?
- *
- * @param name The string to test.
- * @return True only if the given string can be used as a cookie's name.
- */
- @CheckReturnValue
- public static boolean isCookieName(String name) {
- return !name.isEmpty()
- && COOKIE_NAME.matchesAllOf(name)
- && noLeadingOrTrailingWhitespace(name);
- }
-
- /**
- * Is the given string a valid cookie value?
- *
- * @param value The string to test.
- * @return True only if the given string can be used as a cookie's value.
- */
- @CheckReturnValue
- public static boolean isCookieValue(String value) {
- return value.isEmpty()
- || (COOKIE_VALUE.matchesAllOf(value)
- && noLeadingOrTrailingWhitespace(value));
- }
-
- private static boolean noLeadingOrTrailingWhitespace(String string) {
- return !WSP.matches(string.charAt(0))
- && !WSP.matches(string.charAt(string.length() - 1));
- }
-
- // **************** Date parser ****************
-
- @VisibleForTesting
- static long parseDate(String string) {
- int[] hms = null;
- int dayOfMonth = -1;
- int month = -1;
- int year = -1;
- for (String token : tokenizeDate(string)) {
- if (hms == null) {
- hms = parseTimeToken(token);
- if (hms != null) {
- continue;
- }
- }
- if (dayOfMonth < 0) {
- dayOfMonth = parseDayOfMonthToken(token);
- if (dayOfMonth >= 0) {
- continue;
- }
- }
- if (month < 0) {
- month = parseMonthToken(token);
- if (month >= 0) {
- continue;
- }
- }
- if (year < 0) {
- year = parseYearToken(token);
- }
- }
- if (year >= 0 && year < 70) {
- year += 2000;
- } else if (year >= 70 && year < 100) {
- year += 1900;
- }
- String message = null;
- if (hms == null) {
- message = "no time seen";
- } else if (hms[0] > 23) {
- message = String.format("hour too large: %d", hms[0]);
- } else if (hms[1] > 59) {
- message = String.format("minute too large: %d", hms[1]);
- } else if (hms[2] > 59) {
- message = String.format("second too large: %d", hms[2]);
- } else if (dayOfMonth < 0) {
- message = "no day of month seen";
- } else if (dayOfMonth == 0 || dayOfMonth > 31) {
- message = String.format("illegal day of month: %d", dayOfMonth);
- } else if (month < 0) {
- message = "no month seen";
- } else if (year < 0) {
- message = "no year seen";
- } else if (year < 1601) {
- message = String.format("year too small: %d", year);
- }
- if (message != null) {
- throw new IllegalArgumentException(parseDateMessage(message, string));
- }
- Calendar calendar = Calendar.getInstance(GMT, Locale.US);
- calendar.setLenient(false);
- calendar.set(year, month, dayOfMonth, hms[0], hms[1], hms[2]);
- try {
- return calendar.getTimeInMillis();
- } catch (IllegalArgumentException e) {
- throw new IllegalArgumentException(parseDateMessage(e.getMessage(), string));
- }
- }
-
- private static List<String> tokenizeDate(String string) {
- ImmutableList.Builder<String> listBuilder = ImmutableList.builder();
- StringBuilder tokenBuilder = null;
- for (int i = 0; i < string.length(); i += 1) {
- char c = string.charAt(i);
- if (DATE_DELIMITER.matches(c)) {
- if (tokenBuilder != null) {
- listBuilder.add(tokenBuilder.toString());
- tokenBuilder = null;
- }
- } else {
- if (tokenBuilder == null) {
- tokenBuilder = new StringBuilder();
- }
- tokenBuilder.append(c);
- }
- }
- if (tokenBuilder != null) {
- listBuilder.add(tokenBuilder.toString());
- }
- return listBuilder.build();
- }
-
- private static final CharMatcher DATE_DELIMITER =
- CharMatcher.is('\t')
- .or(CharMatcher.inRange('\u0020', '\u002F'))
- .or(CharMatcher.inRange('\u003B', '\u0040'))
- .or(CharMatcher.inRange('\u005B', '\u0060'))
- .or(CharMatcher.inRange('\u007B', '\u007E'));
-
- private static int[] parseTimeToken(String token) {
- Matcher m = applyPattern(TIME_PATTERN, token);
- if (m == null) {
- return null;
- }
- int[] hms = new int[3];
- hms[0] = Integer.valueOf(m.group(1));
- hms[1] = Integer.valueOf(m.group(2));
- hms[2] = Integer.valueOf(m.group(3));
- return hms;
- }
-
- private static final Pattern TIME_PATTERN =
- Pattern.compile("([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})");
-
- private static int parseDayOfMonthToken(String token) {
- Matcher m = applyPattern(DAY_OF_MONTH_PATTERN, token);
- return (m != null) ? Integer.valueOf(m.group()) : -1;
- }
-
- private static final Pattern DAY_OF_MONTH_PATTERN = Pattern.compile("[0-9]{1,2}");
-
- private static int parseMonthToken(String token) {
- if (token.length() < 3) {
- return -1;
- }
- String p = token.substring(0, 3);
- for (Map.Entry<String, Integer> entry : MONTHS.entrySet()) {
- if (entry.getKey().equalsIgnoreCase(p)) {
- return entry.getValue();
- }
- }
- return -1;
- }
-
- private static final Map<String, Integer> MONTHS;
- static {
- ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
- builder.put("jan", Calendar.JANUARY);
- builder.put("feb", Calendar.FEBRUARY);
- builder.put("mar", Calendar.MARCH);
- builder.put("apr", Calendar.APRIL);
- builder.put("may", Calendar.MAY);
- builder.put("jun", Calendar.JUNE);
- builder.put("jul", Calendar.JULY);
- builder.put("aug", Calendar.AUGUST);
- builder.put("sep", Calendar.SEPTEMBER);
- builder.put("oct", Calendar.OCTOBER);
- builder.put("nov", Calendar.NOVEMBER);
- builder.put("dec", Calendar.DECEMBER);
- MONTHS = builder.build();
- }
-
- private static int parseYearToken(String token) {
- Matcher m = applyPattern(YEAR_PATTERN, token);
- return (m != null) ? Integer.valueOf(m.group()) : -1;
- }
-
- private static final Pattern YEAR_PATTERN = Pattern.compile("[0-9]{2,4}");
-
- private static Matcher applyPattern(Pattern pattern, String token) {
- Matcher m = pattern.matcher(token);
- if (m.lookingAt()) {
- int end = m.end();
- if (end == token.length() || !HttpUtil.DIGIT.matches(token.charAt(end))) {
- return m;
- }
- }
- return null;
- }
-
- private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
-
- private static String parseDateMessage(String message, String string) {
- return String.format("Can't parse date string because %s: %s",
- message, Stringify.object(string));
- }
-
- // **************** Constructor ****************
-
- /**
- * Gets a {@link GCookie} with just a name and a value.
- *
- * @param name The name of the cookie to build.
- * @param value The value of the cookie to build.
- * @return A {@link GCookie}.
- * @throws IllegalArgumentException if {@code name} doesn't satisfy
- * {@link #isCookieName} or if {@code value} doesn't satisfy
- * {@link #isCookieValue}.
- */
- @CheckReturnValue
- @Nonnull
- public static GCookie make(String name, String value) {
- return builder(name).setValue(value).build();
- }
-
- /**
- * Gets a builder for constructing a {@link GCookie}.
- *
- * @param name The name of the cookie to build.
- * @return A {@link GCookie} builder.
- * @throws IllegalArgumentException if {@code name} doesn't satisfy
- * {@link #isCookieName}.
- */
- @CheckReturnValue
- @Nonnull
- public static Builder builder(String name) {
- return new Builder(name, DateTimeUtils.currentTimeMillis());
- }
-
- /**
- * Gets a builder for constructing a {@link GCookie}.
- *
- * @param name The name of the cookie to build.
- * @param now The current time in milliseconds since the epoch.
- * @return A {@link GCookie} builder.
- * @throws IllegalArgumentException if {@code name} doesn't satisfy
- * {@link #isCookieName} or if {@code now} is negative.
- */
- @CheckReturnValue
- @Nonnull
- public static Builder builder(String name, long now) {
- return new Builder(name, now);
- }
-
- /**
- * Gets a builder for constructing a {@link GCookie}.
- *
- * @param key The key of the cookie to build.
- * @return A {@link GCookie} builder.
- */
- @CheckReturnValue
- @Nonnull
- public static Builder builder(Key key) {
- return builder(key.getName())
- .setDomain(key.getDomain())
- .setPath(key.getPath());
- }
-
- /**
- * Gets a builder for constructing a {@link GCookie}.
- *
- * @param cookie A cookie to use to pre-populate the builder.
- * @return A {@link GCookie} builder.
- */
- @CheckReturnValue
- @Nonnull
- public static Builder builder(Cookie cookie) {
- return builder(cookie.getName()).setFromCookie(cookie);
- }
-
- /**
- * Gets a builder for constructing a {@link GCookie}.
- *
- * @param cookie A cookie to use to pre-populate the builder.
- * @return A {@link GCookie} builder.
- */
- @CheckReturnValue
- @Nonnull
- public static Builder builder(GCookie cookie) {
- return builder(cookie.getName()).setFromCookie(cookie);
- }
-
- /**
- * A builder class for {@link GCookie} instances.
- */
- @NotThreadSafe
- @ParametersAreNonnullByDefault
- public static final class Builder {
- @Nonnull private final String name;
- @Nonnegative private final long now;
- @Nonnull private String value = "";
- private long expires = -1;
- @Nonnull private String domain = "";
- @Nonnull private String path = "";
- private long creationTime = -1;
- private long lastAccessTime = -1;
- private boolean persistent = false;
- private boolean hostOnly = false;
- private boolean secureOnly = false;
- private boolean httpOnly = false;
- private boolean maxAgeSet = false;
- private long maxAge;
-
- private Builder(String name, @Nonnegative long now) {
- Preconditions.checkArgument(isCookieName(name),
- "Illegal name: %s", name);
- Preconditions.checkArgument(now >= 0,
- "Illegal time: %s", now);
- this.name = name;
- this.now = now;
- }
-
- /**
- * Builds the cookie using the parameters accumulated by the builder.
- *
- * @return A newly created {@link GCookie}.
- */
- @CheckReturnValue
- @Nonnull
- public GCookie build() {
- long at = computeLastAccessTime();
- long ct = computeCreationTime(at);
- return new GCookie(new Key(name, domain, path), value, computeExpires(ct), ct, at,
- computePersistent(), hostOnly, secureOnly, httpOnly);
- }
-
- // The following computations assume that:
- // 1. If maxAgeSet is true, maxAge is preferred to expires and persistent.
- // 2. creationTime is either negative or <= now.
- // 3. lastAccessTime is either negative or <= now.
- // 4. When finished, creationTime <= lastAccessTime.
-
- private long computeLastAccessTime() {
- return (lastAccessTime < 0) ? now : lastAccessTime;
- }
-
- private long computeCreationTime(long lastAccessTime) {
- return (creationTime < 0 || lastAccessTime < creationTime)
- ? lastAccessTime
- : creationTime;
- }
-
- private long computeExpires(long creationTime) {
- return maxAgeSet
- ? ((maxAge < 0) ? Long.MAX_VALUE : creationTime + (maxAge * 1000))
- : ((expires < 0) ? Long.MAX_VALUE : expires);
- }
-
- private boolean computePersistent() {
- return maxAgeSet ? (maxAge >= 0) : persistent;
- }
-
- /**
- * Sets the value of the {@link GCookie} being built.
- *
- * @param value The value.
- * @return This builder, for convenience.
- * @throws IllegalArgumentException if {@code value} doesn't satisfy
- * {@link #isCookieValue}.
- */
- @Nonnull
- public Builder setValue(String value) {
- Preconditions.checkArgument(isCookieValue(value),
- "Illegal value: %s", value);
- this.value = value;
- return this;
- }
-
- /**
- * Sets the expiration time of the {@link GCookie} being built.
- *
- * @param expires The expiration time.
- * @return This builder, for convenience.
- * @throws IllegalArgumentException if the argument is invalid.
- */
- @Nonnull
- public Builder setExpires(@Nonnegative long expires) {
- Preconditions.checkArgument(expires >= 0,
- "Illegal expires: %s", expires);
- this.expires = expires;
- return this;
- }
-
- /**
- * Sets the maximum age of the {@link GCookie} being built. Translates this
- * age into the "expires" and "persistent" attributes of the resulting
- * cookie.
- *
- * @param maxAge The maximum age in seconds.
- * @return This builder, for convenience.
- */
- @Nonnull
- public Builder setMaxAge(long maxAge) {
- this.maxAge = maxAge;
- maxAgeSet = true;
- return this;
- }
-
- /**
- * Sets the domain of the {@link GCookie} being built.
- *
- * @param domain The domain.
- * @return This builder, for convenience.
- */
- @Nonnull
- public Builder setDomain(String domain) {
- this.domain = canonicalizeDomain(domain);
- return this;
- }
-
- /**
- * Sets the path of the {@link GCookie} being built.
- *
- * @param path The path.
- * @return This builder, for convenience.
- * @throws IllegalArgumentException if the argument is invalid.
- */
- @Nonnull
- public Builder setPath(String path) {
- Preconditions.checkArgument(path.isEmpty() || firstChar(path) == PATH_SEPARATOR,
- "Illegal path: %s", path);
- this.path = path;
- return this;
- }
-
- /**
- * Sets the creation time of the {@link GCookie} being built.
- *
- * @param creationTime The creation time.
- * @return This builder, for convenience.
- * @throws IllegalArgumentException if the argument is invalid.
- */
- @Nonnull
- public Builder setCreationTime(@Nonnegative long creationTime) {
- Preconditions.checkArgument(creationTime >= 0 && creationTime <= now,
- "Illegal creation time: %s", creationTime);
- this.creationTime = creationTime;
- return this;
- }
-
- /**
- * Sets the last-access time of the {@link GCookie} being built.
- *
- * @param lastAccessTime The last-access time.
- * @return This builder, for convenience.
- * @throws IllegalArgumentException if the argument is invalid.
- */
- @Nonnull
- public Builder setLastAccessTime(@Nonnegative long lastAccessTime) {
- Preconditions.checkArgument(lastAccessTime >= 0 && lastAccessTime <= now,
- "Illegal last-access time: %s", lastAccessTime);
- this.lastAccessTime = lastAccessTime;
- return this;
- }
-
- /**
- * Sets whether the {@link GCookie} being built is persistent.
- *
- * @param persistent True if the cookie is persistent.
- * @return This builder, for convenience.
- */
- @Nonnull
- public Builder setPersistent(boolean persistent) {
- this.persistent = persistent;
- return this;
- }
-
- /**
- * Sets whether the {@link GCookie} being built is restricted to "secure"
- * connections.
- *
- * @param secureOnly True if the cookie is restricted.
- * @return This builder, for convenience.
- */
- @Nonnull
- public Builder setSecureOnly(boolean secureOnly) {
- this.secureOnly = secureOnly;
- return this;
- }
-
- /**
- * Sets whether the {@link GCookie} being built is restricted to the host
- * that exactly matches its domain.
- *
- * @param hostOnly True if the cookie is restricted.
- * @return This builder, for convenience.
- */
- @Nonnull
- public Builder setHostOnly(boolean hostOnly) {
- this.hostOnly = hostOnly;
- return this;
- }
-
- /**
- * Sets whether the {@link GCookie} being built should be restricted to the
- * HTTP messages. In other words, if true, Javascript client programs can't
- * access this cookie.
- *
- * @param httpOnly If true, the cookie should be restricted.
- * @return This builder, for convenience.
- */
- @Nonnull
- public Builder setHttpOnly(boolean httpOnly) {
- this.httpOnly = httpOnly;
- return this;
- }
-
- /**
- * Sets the fields of the {@link GCookie} being built by copying them from a
- * given cookie. All fields in the given cookie, other than the name and
- * value, are copied to the new {@link GCookie}.
- *
- * @param cookie The cookie to copy them from.
- * @return This builder, for convenience.
- */
- @Nonnull
- public Builder setFromCookie(Cookie cookie) {
- setValue(cookie.getValue());
- setMaxAge(cookie.getMaxAge());
- setDomain(cookie.getDomain());
- setPath(cookie.getPath());
- setSecureOnly(cookie.getSecure());
- return this;
- }
-
- /**
- * Sets the fields of the {@link GCookie} being built by copying them from a
- * given cookie. All fields in the given cookie, other than the name and
- * value, are copied to the new {@link GCookie}.
- *
- * @param cookie The cookie to copy them from.
- * @return This builder, for convenience.
- */
- @Nonnull
- public Builder setFromCookie(GCookie cookie) {
- setValue(cookie.getValue());
- setExpires(cookie.getExpires());
- setDomain(cookie.getDomain());
- setPath(cookie.getPath());
- setCreationTime(cookie.getCreationTime());
- setLastAccessTime(cookie.getLastAccessTime());
- setPersistent(cookie.getPersistent());
- setHostOnly(cookie.getHostOnly());
- setSecureOnly(cookie.getSecureOnly());
- setHttpOnly(cookie.getHttpOnly());
- return this;
- }
- }
-
- // **************** Interface with HTTP request/response ****************
-
- /**
- * Parses cookies from the headers of an HTTP request.
- *
- * @param request The request to get the headers from.
- * @param sessionId A session ID to add to log messages.
- * @param store A cookie store to which the parsed cookies will be added.
- */
- public static void parseHttpRequestCookies(HttpServletRequest request, String sessionId,
- CookieStore store) {
- parseRequestHeaders(
- HttpUtil.getRequestHeaderValues(HttpUtil.HTTP_HEADER_COOKIE, request),
- HttpUtil.getRequestUri(request, false),
- sessionId,
- store);
- }
-
- /**
- * Parses cookies from the headers of an HTTP request.
- *
- * @param request The request to get the headers from.
- * @param sessionId A session ID to add to log messages.
- * @return A cookie store containing the parsed cookies.
- */
- public static CookieStore parseHttpRequestCookies(HttpServletRequest request, String sessionId) {
- CookieStore store = makeStore();
- parseHttpRequestCookies(request, sessionId, store);
- return store;
- }
-
- /**
- * Adds a cookie to an HTTP response.
- *
- * @param cookie The cookie to add.
- * @param response The response to save the cookie header in.
- */
- public static void addHttpResponseCookie(GCookie cookie, HttpServletResponse response) {
- response.addCookie(cookie.toCookie());
- response.addHeader(HttpUtil.HTTP_HEADER_SET_COOKIE, cookie.responseHeaderString(true));
- }
-
- /**
- * Adds cookies to an HTTP response.
- *
- * @param cookies The cookies to add.
- * @param response The response to save the cookie headers in.
- */
- public static void addHttpResponseCookies(Iterable<GCookie> cookies,
- HttpServletResponse response) {
- for (GCookie cookie : cookies) {
- addHttpResponseCookie(cookie, response);
- }
- }
-
- // **************** JSON ****************
-
- public static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(GCookie.class,
- ProxyTypeAdapter.make(GCookie.class, GCookie.LocalProxy.class));
- }
-
- private static final class LocalProxy implements TypeProxy<GCookie> {
- String name;
- String value;
- long expires;
- String domain;
- String path;
- long creationTime;
- long lastAccessTime;
- boolean persistent;
- boolean hostOnly;
- boolean secureOnly;
- boolean httpOnly;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(GCookie cookie) {
- name = cookie.getName();
- value = cookie.getValue();
- expires = cookie.getExpires();
- domain = cookie.getDomain();
- path = cookie.getPath();
- creationTime = cookie.getCreationTime();
- lastAccessTime = cookie.getLastAccessTime();
- persistent = cookie.getPersistent();
- hostOnly = cookie.getHostOnly();
- secureOnly = cookie.getSecureOnly();
- httpOnly = cookie.getHttpOnly();
- }
-
- @Override
- public GCookie build() {
- return builder(name)
- .setValue(value)
- .setExpires(expires)
- .setDomain(domain)
- .setPath(path)
- .setCreationTime(creationTime)
- .setLastAccessTime(lastAccessTime)
- .setPersistent(persistent)
- .setHostOnly(hostOnly)
- .setSecureOnly(secureOnly)
- .setHttpOnly(httpOnly)
- .build();
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/common/HttpUtil.java b/src/com/google/enterprise/secmgr/common/HttpUtil.java
deleted file mode 100644
index 0aab54c..0000000
--- a/src/com/google/enterprise/secmgr/common/HttpUtil.java
+++ /dev/null
@@ -1,825 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.common;
-
-import com.google.common.base.CharMatcher;
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Multimap;
-
-import org.springframework.mock.web.MockHttpServletRequest;
-
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * Static methods for fetching pages via HTTP. See RFCs 2616 and 2617 for
- * details.
- */
-public final class HttpUtil {
-
- public static final String HTTP_METHOD_GET = "GET";
- public static final String HTTP_METHOD_POST = "POST";
- public static final String HTTP_METHOD_HEAD = "HEAD";
-
- // HTTP header names.
- public static final String HTTP_HEADER_ACCEPT = "Accept";
- public static final String HTTP_HEADER_ACCEPT_CHARSET = "Accept-Charset";
- public static final String HTTP_HEADER_ACCEPT_ENCODING = "Accept-Encoding";
- public static final String HTTP_HEADER_ACCEPT_LANGUAGE = "Accept-Language";
- public static final String HTTP_HEADER_AUTHORIZATION = "Authorization";
- public static final String HTTP_HEADER_CONNECTION = "Connection";
- public static final String HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
- public static final String HTTP_HEADER_COOKIE = "Cookie";
- public static final String HTTP_HEADER_DATE = "Date";
- public static final String HTTP_HEADER_LOCATION = "Location";
- public static final String HTTP_HEADER_PROXY_AUTHENTICATE = "Proxy-Authenticate";
- public static final String HTTP_HEADER_PROXY_AUTHORIZATION = "Proxy-Authorization";
- public static final String HTTP_HEADER_RANGE = "Range";
- public static final String HTTP_HEADER_SET_COOKIE = "Set-Cookie";
- public static final String HTTP_HEADER_SET_COOKIE2 = "Set-Cookie2";
- public static final String HTTP_HEADER_USER_AGENT = "User-Agent";
- public static final String HTTP_HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
-
- // TODO(kstillson): The rest of this file is general purpose http, but
- // this cookie-cracking code is quite security manager specific. At some
- // point, it would be good to refactor (perhaps providing a caller
- // specified callback for custom header processing?)
- //
- // TODO(kstillson): make this extensible/configurable (at least from spring).
- // These are Google-specific headers set in a response, which can set the
- // username and groups list for a credentials group.
- public static final String COOKIE_CRACK_USERNAME_HEADER = "X-Username";
- public static final String COOKIE_CRACK_GROUPS_HEADER = "X-Groups";
-
- // Boilerplate HTTP header values.
- public static final String KEEP_ALIVE = "keep-alive";
- // TODO(michellez): make this configurable through spring.
- public static final String USER_AGENT = "SecMgr";
- public static final String ACCEPT =
- "text/html, text/xhtml;q=0.9, text/plain;q=0.5, text/*;q=0.1";
- public static final String ACCEPT_FOR_HEAD = "*/*";
- public static final String ACCEPT_CHARSET = "us-ascii, iso-8859-1, utf-8";
- public static final String ACCEPT_ENCODING = "identity";
- public static final String ACCEPT_LANGUAGE = "en-us, en;q=0.9";
- private static final String RANGE_FORMAT = "bytes=0-%d";
-
- public static final char PARAM_VALUE_SEPARATOR = '=';
- public static final char STRING_DELIMITER = '"';
- public static final char STRING_QUOTE = '\\';
- public static final char PARAM_SEPARATOR_CHAR = ';';
- public static final String PARAM_SEPARATOR = "; ";
-
- // Don't instantiate.
- private HttpUtil() {
- throw new UnsupportedOperationException();
- }
-
- public static boolean isHttpGetMethod(String method) {
- return HTTP_METHOD_GET.equalsIgnoreCase(method);
- }
-
- public static boolean isHttpPostMethod(String method) {
- return HTTP_METHOD_POST.equalsIgnoreCase(method);
- }
-
- public static boolean isHttpHeadMethod(String method) {
- return HTTP_METHOD_HEAD.equalsIgnoreCase(method);
- }
-
- /*
- // Commented out to prevent pulling in ServletBase.
- public static List<StringPair> getBoilerplateHeaders() {
- return getBoilerplateHeaders(false);
- }
-
- public static List<StringPair> getBoilerplateHeaders(boolean isHeadRequest) {
- String accept = isHeadRequest ? ACCEPT_FOR_HEAD : ACCEPT;
- return ImmutableList.of(
- new StringPair(HTTP_HEADER_ACCEPT, accept),
- new StringPair(HTTP_HEADER_ACCEPT_CHARSET, ACCEPT_CHARSET),
- new StringPair(HTTP_HEADER_ACCEPT_ENCODING, ACCEPT_ENCODING),
- new StringPair(HTTP_HEADER_ACCEPT_LANGUAGE, ACCEPT_LANGUAGE),
- new StringPair(HTTP_HEADER_DATE, ServletBase.httpDateString()));
- }*/
-
- /**
- * Does the given HTTP status code indicate a valid response?
- *
- * @param status The status code to test.
- * @return True only if it indicates a valid response.
- */
- public static boolean isGoodHttpStatus(int status) {
- return status == HttpServletResponse.SC_OK
- || status == HttpServletResponse.SC_PARTIAL_CONTENT;
- }
-
- public static URL urlFromString(String urlString) {
- try {
- return new URL(urlString);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- public static URL urlFromString(URL baseUrl, String urlString) {
- try {
- return new URL(baseUrl, urlString);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- public static URL urlFromParts(String protocol, String host, int port, String file) {
- try {
- return new URL(protocol, host, port, file);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- public static URL parseUrlString(String urlString) {
- try {
- return new URL(urlString);
- } catch (MalformedURLException e) {
- return null;
- }
- }
-
- public static URL parseUrlString(URL baseUrl, String urlString) {
- try {
- return new URL(baseUrl, urlString);
- } catch (MalformedURLException e) {
- return null;
- }
- }
-
- public static URL parentUrl(URL url) {
- String path = url.getPath();
- int slash = path.lastIndexOf('/');
- if (slash <= 0) {
- return null;
- }
- return urlFromParts(url.getProtocol(), url.getHost(), url.getPort(), path.substring(0, slash));
- }
-
- public static URL stripQueryFromUrl(URL url) {
- return mergeQueryIntoUrl(url, null);
- }
-
- public static URL mergeQueryIntoUrl(URL url, String query) {
- return urlFromParts(url.getProtocol(), url.getHost(), url.getPort(),
- newQuery(url.getPath(), query));
- }
-
- private static String newQuery(String path, String query) {
- return Strings.isNullOrEmpty(query) ? path : path + "?" + query;
- }
-
- /**
- * Converts a {@link URL} to a {@link URI}.
- *
- * @param url The URL to convert.
- * @return The corresponding URI.
- * @throws IllegalArgumentException if there are any parse errors in the
- * conversion.
- */
- public static URI toUri(URL url) {
- return URI.create(url.toString());
- }
-
- /**
- * Takes a given URI and returns a new one in which the query component has
- * been replaced with a given query string.
- *
- * @param uri The base URI.
- * @param query The new query component; may be {@code null} to delete the
- * query component.
- * @return A suitably modified URI.
- */
- public static URI replaceUriQuery(URI uri, String query) {
- try {
- return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(),
- uri.getPath(), query, uri.getFragment());
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Decodes an application/x-www-form-urlencoded format query string into its
- * component parameters.
- *
- * @param uri A URI to decode the query string of.
- * @return A multimap containing the decoded parameters from the uri.
- * @throws IllegalArgumentException if the URI's query isn't correctly formatted.
- */
- public static ListMultimap<String, String> decodeQueryString(URI uri) {
- return decodeQueryString(uri.getQuery());
- }
-
- /**
- * Decodes an application/x-www-form-urlencoded format query string into its
- * component parameters.
- *
- * @param string The query string to decode.
- * @return A multimap containing the decoded parameters from the string.
- * @throws IllegalArgumentException if the string isn't correctly formatted.
- */
- public static ListMultimap<String, String> decodeQueryString(String string) {
- ListMultimap<String, String> result = ArrayListMultimap.create();
- if (!Strings.isNullOrEmpty(string)) {
- for (String element : QUERY_SPLITTER.split(string)) {
- int index = element.indexOf('=');
- if (index < 0) {
- result.put(element, null);
- } else {
- result.put(element.substring(0, index), element.substring(index + 1));
- }
- }
- }
- return result;
- }
-
- /**
- * Encodes a multimap of query parameters in application/x-www-form-urlencoded
- * format.
- *
- * @param parameters The query parameters to be encoded.
- * @return The encoded string.
- */
- public static String encodeQueryString(Multimap<String, String> parameters) {
- StringBuilder builder = new StringBuilder();
- boolean needSeparator = false;
- for (Map.Entry<String, String> entry : parameters.entries()) {
- if (needSeparator) {
- builder.append('&');
- } else {
- needSeparator = true;
- }
- builder.append(entry.getKey());
- if (entry.getValue() != null) {
- builder.append('=');
- builder.append(entry.getValue());
- }
- }
- return builder.toString();
- }
-
- private static final Splitter QUERY_SPLITTER = Splitter.on('&');
-
- /**
- * Gets the URI for an HTTP request.
- *
- * @param request The HTTP request to get the URI from.
- * @param includeQuery If true, include the query part of the URI.
- * @return The request URI.
- * @throws IllegalArgumentException if the request's URI can't be parsed.
- */
- public static URI getRequestUri(HttpServletRequest request, boolean includeQuery) {
- URI uri = (request instanceof MockHttpServletRequest)
- ? getMockRequestUri((MockHttpServletRequest) request)
- : URI.create(request.getRequestURL().toString());
- return includeQuery
- ? uri
- : replaceUriQuery(uri, null);
- }
-
- private static URI getMockRequestUri(MockHttpServletRequest request) {
- // Note that it's not OK to call request.getRequestURL() because the mock
- // implementation is broken and will include ":-1" if there's no port
- // specified.
- try {
- return new URI(request.getScheme(), null, request.getServerName(), request.getServerPort(),
- request.getRequestURI(), request.getQueryString(), null);
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Gets the URL for an HTTP request.
- *
- * @param request The HTTP request to get the URL from.
- * @param includeQuery If true, include the query part of the URL.
- * @return The request URL.
- * @throws IllegalArgumentException if the request's URL can't be parsed.
- */
- public static URL getRequestUrl(HttpServletRequest request, boolean includeQuery) {
- try {
- return getRequestUri(request, includeQuery).toURL();
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Given a URL, gets a string suitable for logging. This string omits the URL
- * query, as it might contain sensitive parameters that shouldn't be logged
- * (e.g. a password). It also omits the fragment identifier, since that isn't
- * usually needed in the log.
- *
- * @param url The URL to get a log string for.
- * @return An appropriate string representation of the URL.
- */
- public static String getUrlLogString(URL url) {
- return getUriLogString(toUri(url));
- }
-
- /**
- * Given a URL string, gets a string suitable for logging. This string omits
- * the URL query, as it might contain sensitive parameters that shouldn't be
- * logged (e.g. a password). It also omits the fragment identifier, since
- * that isn't usually needed in the log.
- *
- * @param urlString The URL string to get a log string for.
- * @return An appropriate string representation of the URL.
- */
- public static String getUrlLogString(String urlString) {
- URI uri;
- try {
- uri = new URI(urlString);
- } catch (URISyntaxException e) {
- // Dumb, but in the unlikely event we get the exception, it should serve.
- int index = urlString.indexOf('?');
- return (index >= 0)
- ? urlString.substring(0, index)
- : urlString;
- }
- return getUriLogString(uri);
- }
-
- /**
- * Given a URI, gets a string suitable for logging. This string omits the URI
- * query, as it might contain sensitive parameters that shouldn't be logged
- * (e.g. a password). It also omits the fragment identifier, since that isn't
- * usually needed in the log.
- *
- * @param uri The URI to get a log string for.
- * @return An appropriate string representation of the URL.
- */
- public static String getUriLogString(URI uri) {
- try {
- return (new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), null, null))
- .toASCIIString();
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Gets the header value strings for any headers matching a given name.
- *
- * @param name The header name to look for.
- * @param request The request to look in.
- * @return The header values as an immutable list.
- */
- public static ImmutableList<String> getRequestHeaderValues(String name,
- HttpServletRequest request) {
- ImmutableList.Builder<String> builder = ImmutableList.builder();
- Enumeration<?> e = request.getHeaders(name);
- while (e.hasMoreElements()) {
- builder.add(String.class.cast(e.nextElement()));
- }
- return builder.build();
- }
-
- /**
- * Parse an HTTP header parameter. Parameters come in two forms:
- *
- * token PARAM_VALUE_SEPARATOR token
- * token PARAM_VALUE_SEPARATOR quoted-string
- *
- * The character set for a "token" is restricted. A "quoted-string" is
- * surrounded by double quotes and can contain nearly all characters, plus
- * escaped characters.
- *
- * @param string The raw parameter string, assumed to have been trimmed of whitespace.
- * @return A list of two strings, the name and the value.
- * @throws IllegalArgumentException if the string can't be parsed.
- */
- public static List<String> parseHttpParameter(String string) {
- int equals = string.indexOf(PARAM_VALUE_SEPARATOR);
- checkParameterArgument(equals >= 0, string);
- String name = string.substring(0, equals);
- checkParameterArgument(isHttpToken(name), string);
- String rawValue = string.substring(equals + 1, string.length());
- return ImmutableList.of(name,
- isHttpToken(rawValue) ? rawValue : parseHttpQuotedString(rawValue));
- }
-
- private static void checkParameterArgument(boolean succeed, String argument) {
- Preconditions.checkArgument(succeed, "Incorrectly formatted HTTP parameter: %s", argument);
- }
-
- /**
- * Is the given string an HTTP token?
- *
- * @param string The string to test.
- * @return True if the string is a valid HTTP token.
- */
- public static boolean isHttpToken(String string) {
- return !Strings.isNullOrEmpty(string) && TOKEN.matchesAllOf(string);
- }
-
- /**
- * Is the given string something that can be encoded as an HTTP quoted-string?
- *
- * @param string The string to test.
- * @return True if the string can be encoded using the quoted-string format.
- */
- public static boolean isQuotedStringEncodable(String string) {
- return string != null && TEXT.matchesAllOf(string);
- }
-
- /**
- * Encodes a string so that it's suitable as an HTTP parameter value. In
- * other words, if the string is an HTTP token, it's self encoding.
- * Otherwise, it is converted to the quoted-string format.
- *
- * @param string The string to be encoded.
- * @return The same string encoded as an HTTP parameter value.
- * @throws IllegalArgumentException if the given string can't be encoded.
- */
- public static String makeHttpParameterValueString(String string) {
- if (isHttpToken(string)) {
- return string;
- }
- StringBuilder builder = new StringBuilder();
- writeQuotedString(string, builder);
- return builder.toString();
- }
-
- /**
- * Writes a string-valued HTTP parameter to a given string builder. The
- * parameter is prefixed by {@link #PARAM_SEPARATOR}.
- *
- * @param name The parameter name, which must satisfy {@link #isHttpToken}.
- * @param value The parameter value, which must satisfy
- * {@link #isQuotedStringEncodable}.
- * @param builder A string builder to write the parameter to.
- * @throws IllegalArgumentException if {@code name} or {@code value} can't be
- * encoded.
- */
- public static void writeParameter(String name, String value, StringBuilder builder) {
- writeParameterName(name, builder);
- builder.append(PARAM_VALUE_SEPARATOR);
- writeParameterValue(value, builder);
- }
-
- /**
- * Writes a boolean-valued HTTP parameter to a given string builder. The
- * parameter is prefixed by {@link #PARAM_SEPARATOR}.
- *
- * @param name The parameter name, which must satisfy {@link #isHttpToken}.
- * @param value The parameter value.
- * @param builder A string builder to write the parameter to.
- * @throws IllegalArgumentException if {@code name} can't be encoded.
- */
- public static void writeParameter(String name, boolean value, StringBuilder builder) {
- if (value) {
- writeParameterName(name, builder);
- }
- }
-
- /**
- * Writes an HTTP parameter name to a given string builder. The name is
- * prefixed by {@link #PARAM_SEPARATOR}.
- *
- * @param name The parameter name, which must satisfy {@link #isHttpToken}.
- * @param builder A string builder to write the name to.
- * @throws IllegalArgumentException if {@code name} can't be encoded.
- */
- public static void writeParameterName(String name, StringBuilder builder) {
- Preconditions.checkArgument(isHttpToken(name));
- builder.append(PARAM_SEPARATOR);
- builder.append(name);
- }
-
- /**
- * Writes an HTTP parameter value to a given string builder.
- *
- * @param value The parameter value, which must satisfy
- * {@link #isQuotedStringEncodable}.
- * @param builder A string builder to write the value to.
- * @throws IllegalArgumentException if {@code value} can't be encoded.
- */
- public static void writeParameterValue(String value, StringBuilder builder) {
- if (isHttpToken(value)) {
- builder.append(value);
- } else {
- writeQuotedString(value, builder);
- }
- }
-
- /**
- * Writes a string to a string builder in HTTP quoted-string format.
- *
- * @param string The string to be written.
- * @param builder A string builder to write the string to.
- * @throws IllegalArgumentException if {@code string} can't be encoded.
- */
- public static void writeQuotedString(String string, StringBuilder builder) {
- Preconditions.checkArgument(isQuotedStringEncodable(string),
- "String can't be encoded as an HTTP parameter value: %s", string);
- builder.append(STRING_DELIMITER);
- for (char c : string.toCharArray()) {
- if (c == STRING_QUOTE || c == STRING_DELIMITER) {
- builder.append(STRING_QUOTE);
- }
- builder.append(c);
- }
- builder.append(STRING_DELIMITER);
- }
-
- /**
- * Parses an HTTP quoted-string.
- *
- * @param string The string to parse.
- * @return The parsed value of the quoted string.
- * @throws IllegalArgumentException if the string isn't a valid quoted-string.
- */
- public static String parseHttpQuotedString(String string) {
- int end = string.length();
- checkQuotedStringArgument(
- (end >= 2
- && string.charAt(0) == STRING_DELIMITER
- && string.charAt(end - 1) == STRING_DELIMITER),
- string);
- StringBuilder builder = new StringBuilder();
- boolean pendingQuote = false;
- for (char c : string.substring(1, end - 1).toCharArray()) {
- if (pendingQuote) {
- pendingQuote = false;
- checkQuotedStringArgument(CHAR.matches(c), string);
- builder.append(c);
- } else if (c == STRING_QUOTE) {
- pendingQuote = true;
- } else {
- checkQuotedStringArgument(QDTEXT.matches(c), string);
- builder.append(c);
- }
- }
- checkQuotedStringArgument(!pendingQuote, string);
- return builder.toString();
- }
-
- /**
- * Gets the http range header value for requesting the first number of bytes.
- *
- * @param bytes The number of bytes to request.
- * @return The range header value
- */
- public static String getRangeString(int bytes) {
- return String.format(RANGE_FORMAT, bytes);
- }
-
- private static void checkQuotedStringArgument(boolean succeed, String argument) {
- Preconditions.checkArgument(succeed, "Incorrectly formatted quoted-string: %s", argument);
- }
-
- // These names are taken directly from RFC 2616.
-
- private static final CharMatcher OCTET = CharMatcher.inRange('\u0000', '\u00ff');
-
- // Not strictly correct: CHAR technically includes CR and LF, but only for
- // line folding. Since we're looking at a post-line-folding string, they
- // shouldn't be present.
- private static final CharMatcher CHAR = difference(CharMatcher.ASCII, CharMatcher.anyOf("\n\r"));
-
- /** ASCII control characters. */
- public static final CharMatcher CTLS =
- CharMatcher.inRange('\u0000', '\u001f').or(CharMatcher.is('\u007f'));
-
- /** ASCII alphabetic characters. */
- public static final CharMatcher ALPHA =
- CharMatcher.anyOf("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
-
- /** ASCII digit characters. */
- public static final CharMatcher DIGIT = CharMatcher.anyOf("0123456789");
-
- /** Linear white space. */
- public static final CharMatcher LWS = CharMatcher.anyOf(" \t");
-
- /** Plain text. */
- public static final CharMatcher TEXT = union(difference(OCTET, CTLS), LWS);
-
- // Text that can be included in a quoted-string without backquotes. Note that
- // RFC 2616 specifies only '"' as an exception, but clearly '\\' needs to be
- // excepted as well.
- private static final CharMatcher QDTEXT = difference(TEXT, CharMatcher.anyOf("\"\\"));
-
- // Separator characters that aren't allowed in most places except inside
- // quoted-strings.
- private static final CharMatcher SEPARATORS = CharMatcher.anyOf("()<>@,;:\\\"/[]?={} \t");
-
- // The constituent characters of a token.
- private static final CharMatcher TOKEN = difference(CharMatcher.ASCII, union(CTLS, SEPARATORS));
-
- private static CharMatcher union(CharMatcher m1, CharMatcher m2) {
- return m1.or(m2);
- }
-
- private static CharMatcher difference(CharMatcher m1, CharMatcher m2) {
- return m1.and(m2.negate());
- }
-
- // HTTP date formats (from RFC 2616):
- //
- // HTTP-date = rfc1123-date | rfc850-date | asctime-date
- // rfc1123-date = wkday "," SP date1 SP time SP "GMT"
- // rfc850-date = weekday "," SP date2 SP time SP "GMT"
- // asctime-date = wkday SP date3 SP time SP 4DIGIT
- // date1 = 2DIGIT SP month SP 4DIGIT
- // ; day month year (e.g., 02 Jun 1982)
- // date2 = 2DIGIT "-" month "-" 2DIGIT
- // ; day-month-year (e.g., 02-Jun-82)
- // date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
- // ; month day (e.g., Jun 2)
- // time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
- // ; 00:00:00 - 23:59:59
- // wkday = "Mon" | "Tue" | "Wed"
- // | "Thu" | "Fri" | "Sat" | "Sun"
- // weekday = "Monday" | "Tuesday" | "Wednesday"
- // | "Thursday" | "Friday" | "Saturday" | "Sunday"
- // month = "Jan" | "Feb" | "Mar" | "Apr"
- // | "May" | "Jun" | "Jul" | "Aug"
- // | "Sep" | "Oct" | "Nov" | "Dec"
-
- private static final String DATE_FORMAT_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
- private static final String DATE_FORMAT_RFC850 = "EEEE, dd-MMM-yy HH:mm:ss zzz";
- private static final String DATE_FORMAT_ASCTIME = "EEE MMM dd HH:mm:ss yyyy";
-
- /**
- * Generates an HTTP date string.
- *
- * @param date A date value specified as a non-negative difference from the
- * epoch in milliseconds.
- * @return An HTTP date string representing that date.
- */
- public static String generateHttpDate(long date) {
- return getDateFormat(DATE_FORMAT_RFC1123).format(new Date(date));
- }
-
- /**
- * Parses an HTTP date string.
- *
- * @param dateString The string to parse.
- * @return The difference, measured in milliseconds, between the specified
- * date and 1970-01-01T00:00:00Z.
- * @throws IllegalArgumentException if the date string can't be parsed.
- */
- public static long parseHttpDate(String dateString) {
- try {
- return parseDate(DATE_FORMAT_RFC1123, dateString);
- } catch (ParseException e) {
- // Fall through to next format.
- }
- try {
- return parseDate(DATE_FORMAT_RFC850, dateString);
- } catch (ParseException e) {
- // Fall through to next format.
- }
- try {
- return parseDate(DATE_FORMAT_ASCTIME, dateString);
- } catch (ParseException e) {
- throw new IllegalArgumentException("Can't parse as HTTP date string: " + dateString);
- }
- }
-
- private static long parseDate(String formatString, String dateString)
- throws ParseException {
- return getDateFormat(formatString).parse(dateString).getTime();
- }
-
- private static DateFormat getDateFormat(String formatString) {
- DateFormat format = new SimpleDateFormat(formatString);
- format.setCalendar(Calendar.getInstance(GMT, Locale.US));
- return format;
- }
-
- private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
-
- /**
- * Is the given string a valid domain name? Uses a fairly restrictive
- * definition, corresponding to the "preferred syntax" of RFC 1034 as updated
- * by RFC 1123.
- *
- * @param string The string to be tested.
- * @return True only if the string is a valid domain name.
- */
- public static boolean isValidDomainName(String string) {
- return parseDomainName(string) != null;
- }
-
- /**
- * Converts a given domain name to its canonical form. This should eventually
- * handle IDNA names, but for now we just canonicalize case.
- *
- * @param domainName The domain name to convert.
- * @return The canonical form for {@code domainName}.
- * @throws IllegalArgumentException if {@code domainName} doesn't satisfy
- * {@code #isValidDomainName}.
- */
- public static String canonicalizeDomainName(String domainName) {
- List<String> labels = parseDomainName(domainName);
- Preconditions.checkArgument(labels != null, "Not a valid domain name: %s", domainName);
- return labelsToDomanName(labels);
- }
-
- /**
- * Gets the "parent domain" name of a domain name.
- *
- * @param domainName The domain name to get the parent domain name of.
- * @return The parent domain name, or {@code null} if there isn't one.
- * @throws IllegalArgumentException if {@code domainName} doesn't satisfy
- * {@code #isValidDomainName}.
- */
- public static String domainNameParent(String domainName) {
- List<String> labels = parseDomainName(domainName);
- Preconditions.checkArgument(labels != null, "Not a valid domain name: %s", domainName);
- if (labels.size() < 2) {
- return null;
- }
- labels.remove(0);
- return labelsToDomanName(labels);
- }
-
- private static List<String> parseDomainName(String domainName) {
- if (!(domainName.length() >= 1 && domainName.length() <= 255)) {
- return null;
- }
- List<String> labels = Lists.newArrayList(DOMAIN_NAME_SPLITTER.split(domainName));
- if (!(labels.size() >= 1 && labels.size() <= 127)) {
- return null;
- }
- for (String label : labels) {
- if (!isValidDomainLabel(label)) {
- return null;
- }
- }
- // Eliminates IPv4 addresses:
- if (DIGIT.matchesAllOf(labels.get(labels.size() - 1))) {
- return null;
- }
- return labels;
- }
-
- private static boolean isValidDomainLabel(String label) {
- return label.length() >= 1
- && label.length() <= 63
- && DOMAIN_LABEL_CHAR.matchesAllOf(label)
- && label.charAt(0) != '-'
- && label.charAt(label.length() - 1) != '-';
- }
-
- private static String labelsToDomanName(List<String> labels) {
- return DOMAIN_NAME_JOINER.join(
- Iterables.transform(labels,
- new Function<String, String>() {
- @Override
- public String apply(String label) {
- return label.toLowerCase(Locale.US);
- }
- }));
- }
-
- private static final CharMatcher DOMAIN_LABEL_CHAR = ALPHA.or(DIGIT).or(CharMatcher.is('-'));
- private static final Splitter DOMAIN_NAME_SPLITTER = Splitter.on('.');
- private static final Joiner DOMAIN_NAME_JOINER = Joiner.on('.');
-}
diff --git a/src/com/google/enterprise/secmgr/common/SecurePasswordHasher.java b/src/com/google/enterprise/secmgr/common/SecurePasswordHasher.java
deleted file mode 100644
index 5621fa6..0000000
--- a/src/com/google/enterprise/secmgr/common/SecurePasswordHasher.java
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.common;
-
-import com.google.common.base.Charsets;
-
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.spec.InvalidKeySpecException;
-import java.util.Arrays;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.crypto.KeyGenerator;
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.PBEKeySpec;
-
-/**
- * This class implements two password hashers. One is based on the
- * PBKDF2 specification using HMAC-SHA256 as the underlying
- * primitive. PBKDF is short for Password-Based Key Derivation
- * Function. Requires JCE provider that implements the
- * "PBKDF2WithHmacSHA1" algorithm. (Briefly, this algorithm and parameter
- * selection provides some protection against certain types of offline
- * password dictionary attacks.) This algorithm is not deterministic,
- * but it allows the possibility of "verifying" a fingerprint.
- *
- * To generate fingerprints, use SecurePasswordHasher.getFingerprint().
- *
- * The other hasher is a simple MAC. It is deterministic, but
- * the key is not saved, which means that it is not possible to
- * verify the hash later. It is the more secure option of the two
- * because an attacker may only try to guess username/passwords by
- * querying the service while it is running.
- *
- * To generate MAC tags, user SecurePasswordHasher.getMac().
- *
- * #################################################################
- * WARNING:
- * This does not safely obfuscate weak passwords. Only use if it
- * is absolutely necessary to store/log information about passwords,
- * and ensure that files with stored fingerprints have appropriate
- * permissions.
- * #################################################################
- *
- * Please see the RFC for more information on password hashing
- * security: http://tools.ietf.org/html/rfc2898.
- */
-public class SecurePasswordHasher {
-
- private static final Logger LOGGER =
- Logger.getLogger(SecurePasswordHasher.class.getName());
-
- private static final SecureRandom prng = new SecureRandom();
-
- private static final int kNumSeedBytes = 16;
- private static final int kNumIterations = 1000;
- private static final int kNumOutputBits = 128;
- private static final String kHashAlgorithm = "PBKDF2WithHmacSHA1";
- private static Mac mac;
-
- static {
- // Initialize the MAC key.
- try {
- KeyGenerator kg = KeyGenerator.getInstance("HmacSHA1");
- mac = Mac.getInstance("HmacSHA1");
- mac.init(kg.generateKey());
- } catch (NoSuchAlgorithmException e) {
- LOGGER.log(Level.SEVERE, "Could not initialize MAC", e);
- mac = null;
- } catch (InvalidKeyException e) {
- LOGGER.log(Level.SEVERE, "Could not initialize MAC", e);
- mac = null;
- }
- }
-
- /**
- * We don't want this class to be instantiated.
- */
- private SecurePasswordHasher() {
- }
-
- /**
- * A container for a fingerprint specification. From this fingerprint
- * specification, it should be easy to verify that a given password
- * generated the fingerprint. Finding the password from the fingerprint
- * should be much more difficult as long as the password was "well-chosen".
- */
- public static class Fingerprint {
- private final String hash;
- private final String seed;
- private final String algorithm;
- private final int iterations;
-
- Fingerprint(String hash, String seed, String algorithm, int iterations) {
- this.hash = hash;
- this.seed = seed;
- this.algorithm = algorithm;
- this.iterations = iterations;
- }
-
- public String hash() {
- return hash;
- }
-
- public String seed() {
- return seed;
- }
-
- public String algorithm() {
- return algorithm;
- }
-
- public int iterations() {
- return iterations;
- }
-
- /**
- * Parses a Fingerprint object from a string.
- * @param fingerprint the output of toString() from a
- * Fingerprint object
- */
- public static Fingerprint parseFingerprint(String fingerprint)
- throws IllegalArgumentException {
- String[] parts = fingerprint.split(":");
- if (parts.length != 4) {
- throw new IllegalArgumentException(
- "Incorrectly formatted fingerprint: " + fingerprint);
- }
-
- int iterations;
- try {
- iterations = Integer.parseInt(parts[3]);
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException("Could not parse number of " +
- "iterations from fingerprint: " + fingerprint);
- }
-
- return new Fingerprint(parts[0], parts[1], parts[2], iterations);
- }
-
- @Override
- public String toString() {
- return hash + ":" + seed + ":" + algorithm + ":" + iterations;
- }
-
- @Override
- public int hashCode() {
- return toString().hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof Fingerprint)) {
- return false;
- }
- return toString().equals(((Fingerprint) obj).toString());
- }
- }
-
- /**
- * Produce a fingerprint from an input string. This is non-deterministic
- * and will use safe defaults for the parameters (as of 05/2009).
- */
- public static synchronized Fingerprint getFingerprint(String input) {
- byte[] seed = new byte[kNumSeedBytes];
-
- // Randomly choose a seed.
- synchronized (prng) {
- prng.nextBytes(seed);
- }
-
- byte[] hash = hashString(input, kHashAlgorithm, kNumIterations, seed);
- return new Fingerprint(Base64.encode(hash), Base64.encode(seed),
- kHashAlgorithm, kNumIterations);
- }
-
- /**
- * Returns true iff the input is a valid producer of the given fingerprint.
- * @param input the candidate input string
- * @param fingerprint
- */
- public static boolean verifyFingerprint(String input, Fingerprint fingerprint) {
- byte[] seedBytes;
- try {
- seedBytes = Base64.decode(fingerprint.seed());
- } catch (Base64DecoderException e) {
- LOGGER.warning("Could not base64 decode input string: " + fingerprint.seed());
- return false;
- }
-
- byte[] hashBytes;
- try {
- hashBytes = Base64.decode(fingerprint.hash());
- } catch (Base64DecoderException e) {
- LOGGER.warning("Could not base64 decode input string: " + fingerprint.hash());
- return false;
- }
- return Arrays.equals(hashBytes, hashString(input, fingerprint.algorithm(),
- fingerprint.iterations(), seedBytes));
- }
-
- /**
- * Returns the MAC of the combination of the username and password.
- * The key used to MAC these messages is not saved, so this effectively
- * erases the threat of doing off-line brute force password-guessing.
- * If an attacker has access to the logs, they may mount an on-line
- * attack (querying many different known username/password combos to see
- * if they match unknown username/password MACs), but this is a much
- * more constrained environment.
- *
- * This function is deterministic, however, which enables debugging by
- * tracking that a particular username/password is being used in
- * multiple places or tracking how frequently a user logs in, etc.
- *
- * @param username required so an attacker cannot easily tell if
- * two users have the same password by looking at the logs
- * @param password password to mac
- */
- public static String getMac(String username, String password) {
- return Base64.encode(macInput(username, password));
- }
-
- /**
- * Run the input string through the PBKDF with the given parameters and
- * return the result.
- */
- private static byte[] hashString(String input, String algorithm,
- int iterations, byte[] seed) {
-
- PBEKeySpec keySpec = new PBEKeySpec(input.toCharArray(), seed,
- iterations, kNumOutputBits);
-
- SecretKeyFactory factory;
- try {
- factory = SecretKeyFactory.getInstance(algorithm);
- } catch (NoSuchAlgorithmException e) {
- LOGGER.log(Level.SEVERE, "Could not get key spec", e);
- return new byte[kNumSeedBytes]; // Don't reveal information about the password.
- }
-
- SecretKey hash;
- try {
- hash = factory.generateSecret(keySpec);
- } catch (InvalidKeySpecException e) {
- LOGGER.severe("Could not load hash algorithm: " + e);
- return new byte[kNumSeedBytes]; // Don't reveal information about the password.
- }
- return hash.getEncoded();
- }
-
- /**
- * Returns a one-way keyed function output for the given username and
- * password.
- *
- * @param username required so an attacker cannot easily tell if two users
- * have the same password by looking at the logs
- * @param password password to mac
- */
- public static byte[] macInput(String username, String password) {
- if (mac == null) {
- LOGGER.severe("tried to MAC message when mac object uninitialized");
- return new byte[0];
- }
- return mac.doFinal((username + ":" + password).getBytes(Charsets.UTF_8));
- }
-
- /**
- * This provides a simple command-line tool to verify passwords.
- */
- public static void main(String[] args) throws Throwable {
- int numArgs = args.length;
- if (numArgs < 2 || numArgs > 3) {
- System.err.println("Usage: SecurePasswordHasher password [fingerprint]");
- System.exit(1);
- }
- if (numArgs == 2) {
- System.out.println(SecurePasswordHasher.getFingerprint(args[1])
- .toString());
- } else {
- Fingerprint fingerprint = Fingerprint.parseFingerprint(args[2]);
- boolean verified =
- SecurePasswordHasher.verifyFingerprint(args[1], fingerprint);
- if (verified) {
- System.out.println("Password is correct");
- } else {
- System.out.println("Invalid password");
- }
- }
-
- System.exit(0);
- }
-}
diff --git a/src/com/google/enterprise/secmgr/common/SecurityManagerUtil.java b/src/com/google/enterprise/secmgr/common/SecurityManagerUtil.java
index 87bd887..395d6d3 100644
--- a/src/com/google/enterprise/secmgr/common/SecurityManagerUtil.java
+++ b/src/com/google/enterprise/secmgr/common/SecurityManagerUtil.java
@@ -15,35 +15,9 @@
package com.google.enterprise.secmgr.common;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.BoundedExecutorService;
-import org.joda.time.DateTimeUtils;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.security.SecureRandom;
-import java.util.Collection;
-import java.util.Formatter;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnegative;
-import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
/**
@@ -59,27 +33,6 @@
}
/**
- * Remove all elements specified by a given predicate from a collection.
- *
- * @param iterable The collection to modify.
- * @param predicate The predicate identifying the elements to remove.
- * @return A collection of the elements that were removed.
- */
- public static <T> Collection<T> removeInPlace(Iterable<T> iterable, Predicate<T> predicate) {
- ImmutableList.Builder<T> builder = ImmutableList.builder();
- Iterator<T> iterator = iterable.iterator();
- boolean changed = false;
- while (iterator.hasNext()) {
- T element = iterator.next();
- if (predicate.apply(element)) {
- iterator.remove();
- builder.add(element);
- }
- }
- return builder.build();
- }
-
- /**
* Annotate a log message with a given session ID. This should be implemented
* in the session manager, but can't be due to cyclic build dependencies.
*
@@ -92,72 +45,6 @@
}
/**
- * Generate a random nonce as a byte array.
- *
- * @param nBytes The number of random bytes to generate.
- * @return A randomly generated byte array of the given length.
- */
- public static byte[] generateRandomNonce(int nBytes) {
- byte[] randomBytes = new byte[nBytes];
- synchronized (prng) {
- prng.nextBytes(randomBytes);
- }
- return randomBytes;
- }
-
- /**
- * Generate a random nonce as a hexadecimal string.
- *
- * @param nBytes The number of random bytes to generate.
- * @return A randomly generated hexadecimal string.
- */
- public static String generateRandomNonceHex(int nBytes) {
- return bytesToHex(generateRandomNonce(nBytes));
- }
-
- private static final SecureRandom prng = new SecureRandom();
-
- /**
- * Convert a byte array to a hexadecimal string.
- *
- * @param bytes The byte array to convert.
- * @return The equivalent hexadecimal string.
- */
- public static String bytesToHex(byte[] bytes) {
- Preconditions.checkNotNull(bytes);
- Formatter f = new Formatter();
- for (byte b : bytes) {
- f.format("%02x", b);
- }
- return f.toString();
- }
-
- /**
- * Convert a hexadecimal string to a byte array.
- *
- * @param hexString The hexadecimal string to convert.
- * @return The equivalent array of bytes.
- * @throws IllegalArgumentException if the string isn't valid hexadecimal.
- */
- public static byte[] hexToBytes(String hexString) {
- Preconditions.checkNotNull(hexString);
- int len = hexString.length();
- Preconditions.checkArgument(len % 2 == 0);
- int nBytes = len / 2;
- byte[] decoded = new byte[nBytes];
- int j = 0;
- for (int i = 0; i < nBytes; i += 1) {
- int d1 = Character.digit(hexString.charAt(j++), 16);
- int d2 = Character.digit(hexString.charAt(j++), 16);
- if (d1 < 0 || d2 < 0) {
- throw new IllegalArgumentException("Non-hexadecimal character in string: " + hexString);
- }
- decoded[i] = (byte) ((d1 << 4) + d2);
- }
- return decoded;
- }
-
- /**
* Is a given remote "before" time valid? In other words, is it possible that
* the remote "before" time is less than or equal to the remote "now" time?
*
@@ -187,280 +74,4 @@
}
private static final long CLOCK_SKEW_TIME = 5000;
-
- /**
- * Compare two URLs for equality. Preferable to using the {@link URL#equals}
- * because the latter calls out to DNS and can block.
- *
- * @param url1 A URL to compare.
- * @param url2 Another URL to compare.
- * @return True if the two URLs are the same.
- */
- public static boolean areUrlsEqual(URL url1, URL url2) {
- if (url1 == null || url2 == null) {
- return url1 == null && url2 == null;
- }
- return areStringsEqualIgnoreCase(url1.getProtocol(), url2.getProtocol())
- && areStringsEqualIgnoreCase(url1.getHost(), url2.getHost())
- && url1.getPort() == url2.getPort()
- && areStringsEqual(url1.getFile(), url2.getFile())
- && areStringsEqual(url1.getRef(), url2.getRef());
- }
-
- private static boolean areStringsEqual(String s1, String s2) {
- return s1 == s2 || ((s1 == null) ? s2 == null : s1.equals(s2));
- }
-
- private static boolean areStringsEqualIgnoreCase(String s1, String s2) {
- return s1 == s2 || ((s1 == null) ? s2 == null : s1.equalsIgnoreCase(s2));
- }
-
- /**
- * @return The value of ENT_CONFIG_NAME from the GSA configuration.
- * If not running on a GSA (e.g. for testing), return a fixed string.
- */
- public static String getGsaEntConfigName() {
- String entConfigName = System.getProperty("gsa.entityid");
- if (entConfigName == null) {
- return "testing";
- }
- return entConfigName;
- }
-
- /**
- * @return A URI builder with default scheme and host arguments.
- */
- public static UriBuilder uriBuilder() {
- return new UriBuilder("http", "google.com");
- }
-
- /**
- * @param scheme The URI Scheme to use.
- * @param host The URI host to use.
- * @return A URI builder with the given scheme and host.
- */
- public static UriBuilder uriBuilder(String scheme, String host) {
- return new UriBuilder(scheme, host);
- }
-
- /**
- * A class to build URIs by incrementally specifying their path segments.
- */
- public static final class UriBuilder {
- private final String scheme;
- private final String host;
- private final StringBuilder pathBuilder;
-
- private UriBuilder(String scheme, String host) {
- this.scheme = scheme;
- this.host = host;
- pathBuilder = new StringBuilder();
- }
-
- /**
- * Add a segment to the path being accumulated.
- *
- * @param segment The segment to add.
- * @return The builder, for convenience.
- * @throws IllegalArgumentException if the segment contains any illegal characters.
- */
- public UriBuilder addSegment(String segment) {
- Preconditions.checkArgument(segment != null && !segment.contains("/"),
- "Path segments may not contain the / character: %s", segment);
- pathBuilder.append("/").append(segment);
- return this;
- }
-
- /**
- * Add a hex-encoded random segment to the path being accumulated.
- *
- * @param nBytes The number of random bytes in the segment.
- * @return The builder, for convenience.
- */
- public UriBuilder addRandomSegment(int nBytes) {
- return addSegment(generateRandomNonceHex(nBytes));
- }
-
- /**
- * @return The URI composed of the accumulated parts.
- * @throws IllegalArgumentException if there's a syntax problem with one of the parts.
- */
- public URI build() {
- try {
- return new URI(scheme, host, pathBuilder.toString(), null);
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(e);
- }
- }
- }
-
- private static UriBuilder gsaUriBuilder() {
- return uriBuilder()
- .addSegment("enterprise")
- .addSegment("gsa")
- .addSegment(getGsaEntConfigName());
- }
-
- public static UriBuilder smUriBuilder() {
- return gsaUriBuilder()
- .addSegment("security-manager");
- }
-
- // TODO(cph): make this configurable (preferably in sec mgr config).
- private static final int THREAD_POOL_SIZE = 20;
- private static final ExecutorService THREAD_POOL
- = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
-
- // Batches of work that are themselves parallizable use a 2nd pool to
- // parallelize batches while the 1st pool is used for work within the batches.
- private static final ExecutorService THREAD_POOL_2
- = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
-
- // Timeout difference between THREAD_POOL_1 and THREAD_POOL_2.
- // Otherwise there is a race between their layered use.
- // So when batches are submitted they use THREAD_POOL_2 to manage
- // batches, and THREAD_POOL is given less time to carry out tasks.
- private static final long THREAD_POOL_DELAY_MILLIS = 20;
-
- @VisibleForTesting
- static int getPrimaryThreadPoolSize() {
- return THREAD_POOL_SIZE;
- }
-
- /**
- * Runs a bunch of tasks in parallel using the default/primary thread pool.
- *
- * @param callables The tasks to be run.
- * @param timeoutMillis The maximum amount of time allowed for processing all
- * the tasks.
- * @param sessionId A session ID to use for logging.
- * @return An immutable list of the computed values, in no particular order.
- * The number of values is normally the same as the number of tasks, but
- * if the timeoutMillis is reached or if one or more of the tasks generates an
- * exception, there will be fewer values than tasks.
- */
- @CheckReturnValue
- @Nonnull
- public static <T> List<T> runInParallel(
- @Nonnull Iterable<Callable<T>> callables,
- @Nonnegative long timeoutMillis,
- @Nonnull String sessionId) {
- long endTimeMillis = DateTimeUtils.currentTimeMillis() + timeoutMillis;
- return runInParallel(THREAD_POOL, callables, endTimeMillis, sessionId);
- }
-
- private static long calcRemainingMillis(long endTimeMillis) {
- return endTimeMillis - DateTimeUtils.currentTimeMillis();
- }
-
- @CheckReturnValue
- @Nonnull
- public static <T> List<T> runBatchesInParallel(
- @Nonnull Iterable<KeyedBatchOfCallables<T>> keyedBatches, @Nonnegative long timeoutMillis,
- @Nonnull String sessionId, int maxThreadsPerBatch) {
- long endTimeMillis = DateTimeUtils.currentTimeMillis() + timeoutMillis;
-
- /* Convert each batch of callables (a list of callables) into a single
- callable that has the batch of callables parallelized inside of it */
- List<Callable<List<T>>> callsWithParallization = Lists.newArrayList();
- for (KeyedBatchOfCallables<T> keyedBatch : keyedBatches) {
- Callable<List<T>> oneCallableBatch = keyedBatch
- .toSingleParallelizedCallable(endTimeMillis, sessionId, maxThreadsPerBatch);
- callsWithParallization.add(oneCallableBatch);
- }
-
- List<List<T>> answerLists = runInParallel(THREAD_POOL_2, callsWithParallization,
- endTimeMillis, sessionId);
- ImmutableList.Builder<T> builder = ImmutableList.builder();
- for (List<T> answerList : answerLists) {
- builder.addAll(answerList);
- }
- return builder.build();
- }
-
- @Nonnull
- private static <T> List<T> runInParallel(
- @Nonnull ExecutorService threadPool,
- @Nonnull Iterable<Callable<T>> callables,
- @Nonnegative long endTimeMillis,
- @Nonnull String sessionId) {
- Preconditions.checkNotNull(threadPool);
- Preconditions.checkNotNull(callables);
- Preconditions.checkArgument(endTimeMillis >= 0);
- Preconditions.checkNotNull(sessionId);
-
- List<T> results = Lists.newArrayList();
- try {
- List<Future<T>> futures = threadPool.invokeAll(Lists.newArrayList(callables),
- calcRemainingMillis(endTimeMillis), TimeUnit.MILLISECONDS);
- for (Future<T> f : futures) {
- try {
- if (f.isDone() && !f.isCancelled()) {
- T singleResult = f.get();
- if (null != singleResult) {
- results.add(singleResult);
- }
- }
- } catch (ExecutionException e) {
- LOGGER.log(Level.WARNING,
- SecurityManagerUtil.sessionLogMessage(sessionId, "Exception in worker thread: "),
- e);
- }
- }
-
- } catch (InterruptedException e) {
- // Reset the interrupt, then fall through to the cleanup code below.
- Thread.currentThread().interrupt();
- }
- return results;
- }
-
- // Contains bounded executors per key.
- private static HashMap<String, ExecutorService> boundedServicers
- = new HashMap<String, ExecutorService>();
-
- /** Returns a bounded executor service for a given key, unless
- one doesn't exist already, in which it's constructed with
- maxThreadsPerBatch parameter. Note that if a bounded executor
- service by a given name already exists then it's provided
- without checking that it uses the same number of maxThreadsPerBatch. */
- private static ExecutorService getServiceForKey(String key, int maxThreadsPerBatch) {
- ExecutorService service;
- synchronized(boundedServicers) {
- if (!boundedServicers.containsKey(key)) {
- boundedServicers.put(key, new BoundedExecutorService(maxThreadsPerBatch,
- /*fair*/ false, THREAD_POOL));
- }
- service = boundedServicers.get(key);
- }
- return service;
- }
-
- /** Converts a list of Callables into a single Callable that
- parallizes the original list of work. */
- public static class KeyedBatchOfCallables<T> {
- private final String key;
- private final List<Callable<T>> work;
-
- public KeyedBatchOfCallables(String key, List<Callable<T>> work) {
- this.key = key;
- this.work = ImmutableList.copyOf(work);
- }
-
- /** Returns callable that when invoked performs all the work
- callables provided in constructor in parallel. A BoundedExecutorService
- is used to limit the resources that the parallization takes. */
- private Callable<List<T>> toSingleParallelizedCallable(final long endTimeMillis,
- final String sessionId, int maxThreadsPerBatch) {
- final ExecutorService limitedExecutor = getServiceForKey(key, maxThreadsPerBatch);
- Callable<List<T>> singleCallable = new Callable<List<T>>() {
- @Override
- public List<T> call() {
- return runInParallel(limitedExecutor, work,
- endTimeMillis - THREAD_POOL_DELAY_MILLIS, sessionId);
- }
- };
- return singleCallable;
- }
- }
}
diff --git a/src/com/google/enterprise/secmgr/common/SessionUtil.java b/src/com/google/enterprise/secmgr/common/SessionUtil.java
deleted file mode 100644
index cb2474e..0000000
--- a/src/com/google/enterprise/secmgr/common/SessionUtil.java
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.common;
-
-import com.google.common.base.Preconditions;
-
-import java.util.regex.Pattern;
-
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * A collection of session utilities.
- */
-public final class SessionUtil {
- /**
- * The name of the GSA session ID cookie.
- */
- public static final String GSA_SESSION_ID_COOKIE_NAME = "GSA_SESSION_ID";
-
- /**
- * A regular expression that matches a valid session ID; basically alphanumeric.
- */
- // TODO(cph): might be useful to broaden this pattern to handle base64.
- private static final Pattern SESSION_ID_REGEXP = Pattern.compile("[0-9A-Za-z]*");
-
- /**
- * The smallest acceptable length for a session ID string.
- */
- private static final int MIN_ACCEPTABLE_SESSION_ID_LENGTH = 16;
-
- /**
- * The largest acceptable length for a session ID string.
- */
- private static final int MAX_ACCEPTABLE_SESSION_ID_LENGTH = 100;
-
- /**
- * The length of a generated session ID string.
- */
- private static final int GENERATED_SESSION_ID_LENGTH = MIN_ACCEPTABLE_SESSION_ID_LENGTH;
-
- // Don't instantiate.
- private SessionUtil() {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Generate a session ID for a new session.
- */
- public static String generateId() {
- return SecurityManagerUtil.generateRandomNonceHex(GENERATED_SESSION_ID_LENGTH / 2);
- }
-
- /**
- * Is the given string a valid session ID?
- *
- * @param proposedId The string to test.
- * @return True only if the string is valid.
- */
- public static boolean isValidId(String proposedId) {
- return proposedId != null
- && proposedId.length() >= MIN_ACCEPTABLE_SESSION_ID_LENGTH
- && proposedId.length() <= MAX_ACCEPTABLE_SESSION_ID_LENGTH
- && SESSION_ID_REGEXP.matcher(proposedId).matches();
- }
-
- /**
- * Get the GSA session ID by examining the cookies in an incoming request.
- *
- * @param request The HTTP request to check the cookies of.
- * @return The GSA session ID, if a valid one is found; otherwise null.
- */
- public static String findGsaSessionId(HttpServletRequest request) {
- Preconditions.checkNotNull(request);
- CookieStore cookies = GCookie.parseHttpRequestCookies(request, null);
- for (GCookie c : cookies) {
- if (GSA_SESSION_ID_COOKIE_NAME.equalsIgnoreCase(c.getName())
- && isValidId(c.getValue())) {
- return c.getValue();
- }
- }
- return null;
- }
-}
diff --git a/src/com/google/enterprise/secmgr/common/XmlUtil.java b/src/com/google/enterprise/secmgr/common/XmlUtil.java
index 399c85d..365f447 100644
--- a/src/com/google/enterprise/secmgr/common/XmlUtil.java
+++ b/src/com/google/enterprise/secmgr/common/XmlUtil.java
@@ -14,34 +14,20 @@
package com.google.enterprise.secmgr.common;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-
-import org.w3c.dom.Attr;
-import org.w3c.dom.Comment;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Text;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSException;
-import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSOutput;
-import org.w3c.dom.ls.LSParser;
import org.w3c.dom.ls.LSSerializer;
import java.io.IOException;
-import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
-import java.util.List;
-import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
/**
@@ -157,25 +143,6 @@
}
/**
- * Read an XML document from a file.
- *
- * @param input The stream to read the document from.
- * @return The XML document.
- * @throws IOException if the document can't be parsed.
- */
- public Document readXmlDocument(Reader input)
- throws IOException {
- LSInput lsInput = domImplLs.createLSInput();
- lsInput.setCharacterStream(input);
- LSParser parser = domImplLs.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);
- try {
- return parser.parse(lsInput);
- } catch (LSException e) {
- throw new IOException(e);
- }
- }
-
- /**
* Write an XML document to a writer.
*
* @param document The XML document to write.
@@ -246,338 +213,4 @@
writeXmlDocument(document, output);
return output.toString();
}
-
- /**
- * Add a namespace declaration to the given element.
- *
- * @param element The element to add the declaration to.
- * @param prefix The namespace prefix to declare.
- * @param uri The namespace URI to associate with the given prefix.
- * @return The namespace declaration as an attribute object.
- */
- public static Attr addNamespaceDeclaration(Element element, String prefix, String uri) {
- return makeAttrChild(
- element,
- new QName(
- XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
- prefix,
- XMLConstants.XMLNS_ATTRIBUTE),
- uri);
- }
-
- /**
- * Get the child elements.
- *
- * @param parent The parent element to look in.
- * @return A list of the child elements.
- */
- public static List<Element> getChildElements(Element parent) {
- List<Element> elements = Lists.newArrayList();
- NodeList nodes = parent.getChildNodes();
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- if (node instanceof Element) {
- elements.add((Element) node);
- }
- }
- return elements;
- }
-
- /**
- * Find a child element with a given name.
- *
- * @param parent The parent element to look in.
- * @param qname The qname of the child element to look for.
- * @param required True if the method should throw an exception when no such child.
- * @return The specified child element, or null if non such (and required is false).
- * @throws IllegalArgumentException if required is true and there's no such child.
- */
- public static Element findChildElement(Element parent, QName qname, boolean required) {
- NodeList nodes = parent.getChildNodes();
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- if (isElementWithQname(node, qname)) {
- return (Element) node;
- }
- }
- if (required) {
- throw new IllegalArgumentException(
- "Entity doesn't contain child named " + qname.toString());
- }
- return null;
- }
-
- /**
- * Get the child elements with a given name.
- *
- * @param parent The parent element to look in.
- * @param qname The qname of the child elements to retrieve.
- * @return A list of the child elements with the given tag name.
- */
- public static List<Element> getChildElements(Element parent, QName qname) {
- List<Element> elements = Lists.newArrayList();
- NodeList nodes = parent.getChildNodes();
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- if (isElementWithQname(node, qname)) {
- elements.add((Element) node);
- }
- }
- return elements;
- }
-
- /**
- * Count the child elements with a given name.
- *
- * @param parent The parent element to look in.
- * @param qname The qname of the child elements to look for.
- * @return The number of child elements with the given tag name.
- */
- public static int countChildElements(Element parent, QName qname) {
- int nElements = 0;
- NodeList nodes = parent.getChildNodes();
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- if (isElementWithQname(node, qname)) {
- nElements += 1;
- }
- }
- return nElements;
- }
-
- public static boolean isElementWithQname(Node node, QName qname) {
- return node instanceof Element && elementHasQname((Element) node, qname);
- }
-
- /**
- * Compare an element's tag name to a given name.
- *
- * @param element The element to get the tag name from.
- * @param qname The qname to compare to.
- * @return True if the element's tag name and namespace URI match those of the qname.
- */
- public static boolean elementHasQname(Element element, QName qname) {
- return qname.getLocalPart().equals(element.getLocalName())
- && qname.getNamespaceURI().equals(getNamespaceUri(element));
- }
-
- /**
- * Get the namespace URI of a given element.
- *
- * @param element The element to get the namespace URI of.
- * @return The namespace URI, or the null namespace URI if the element has none.
- */
- public static String getNamespaceUri(Element element) {
- String namespace = element.getNamespaceURI();
- return (namespace != null) ? namespace : XMLConstants.NULL_NS_URI;
- }
-
- /**
- * Get the text from an element that contains only text.
- *
- * @param element The element to get the text from.
- * @return The text contained in that element.
- * @throws IllegalArgumentException if the element isn't text-only.
- */
- public static String getElementText(Element element) {
- NodeList nodes = element.getChildNodes();
- Preconditions.checkArgument(nodes.getLength() == 1
- && nodes.item(0).getNodeType() == Node.TEXT_NODE);
- return nodes.item(0).getNodeValue();
- }
-
- /**
- * Get the text from a child element that contains only text.
- *
- * @param parent The parent element to look in.
- * @param qname The qname of the child element to look for.
- * @param required True if the method should throw an exception when no such child.
- * @return The text of the specified child element, or null if non such (and required is false).
- * @throws IllegalArgumentException if required is true and there's no such child.
- */
- public static String getChildElementText(Element parent, QName qname, boolean required) {
- Element child = findChildElement(parent, qname, required);
- return (child != null) ? getElementText(child) : null;
- }
-
- /**
- * Find all the comments in a given element that contain some given text.
- *
- * @param parent The parent element to look in.
- * @param text The comment string to search for.
- * @return A list of the comments containing that string.
- */
- public static List<Comment> findChildComments(Element parent, String text) {
- List<Comment> comments = Lists.newArrayList();
- NodeList nodes = parent.getChildNodes();
- for (int index = 0; index < nodes.getLength(); index++) {
- Node node = nodes.item(index);
- if (node instanceof Comment && node.getNodeValue().contains(text)) {
- comments.add((Comment) node);
- }
- }
- return comments;
- }
-
- /**
- * Get the descendant elements with a given name.
- *
- * @param parent The parent element to look in.
- * @param qname The qname of the descendant elements to look for.
- * @return A list of the descendant elements with the given tag name.
- */
- public static NodeList getElementsByQname(Element parent, QName qname) {
- return parent.getElementsByTagNameNS(qname.getNamespaceURI(), qname.getLocalPart());
- }
-
- /**
- * Get a given element's attribute with a given name.
- *
- * @param element The element to get the attribute from.
- * @param qname The qname of the attribute to look for.
- * @param required True if the method should throw an exception when no such attribute.
- * @return The attribute's value, or null if no such attribute (and required is false).
- * @throws IllegalArgumentException if no such attribute and required is true.
- */
- public static String findAttribute(Element element, QName qname, boolean required) {
- String ns = qname.getNamespaceURI();
- String localName = qname.getLocalPart();
- if (ns.isEmpty()) {
- ns = null;
- }
- if (element.hasAttributeNS(ns, localName)) {
- String value = element.getAttributeNS(ns, localName);
- return value;
- }
- if (required) {
- throw new IllegalArgumentException(
- "Entity doesn't contain attribute named " + qname.toString());
- }
- return null;
- }
-
- /**
- * Make a new DOM element child.
- *
- * @param parent The element to put the new child element in.
- * @param qname The qname of the new child element.
- * @return The new child element.
- */
- public static Element makeElementChild(Element parent, QName qname) {
- Element child = makeElement(parent, qname);
- parent.appendChild(child);
- return child;
- }
-
- /**
- * Make a new DOM text child.
- *
- * @param parent The element to put the new child text in.
- * @param content The text content of the new child.
- * @return The new child text.
- */
- public static Text makeTextChild(Element parent, String content) {
- Text child = makeText(parent, content);
- parent.appendChild(child);
- return child;
- }
-
- /**
- * Make a new DOM element child containing some text.
- *
- * @param parent The element to put the new child element in.
- * @param qname The name of the new child element.
- * @param content The text content of the new child element.
- * @return The new child element.
- */
- public static Element makeTextElementChild(Element parent, QName qname, String content) {
- Element child = makeElementChild(parent, qname);
- makeTextChild(child, content);
- return child;
- }
-
- /**
- * Make a new DOM comment child.
- *
- * @param parent The element to put the new child comment in.
- * @param content The text content of the new child comment.
- * @return The new child comment.
- */
- public static Comment makeCommentChild(Element parent, String content) {
- Comment child = makeComment(parent, content);
- parent.appendChild(child);
- return child;
- }
-
- /**
- * Make a new DOM attribute child.
- *
- * @param parent The element to put the new child attribute in.
- * @param qname The qname of the new child attribute.
- * @param value The value of the new child attribute.
- * @return The new child attribute.
- */
- public static Attr makeAttrChild(Element parent, QName qname, String value) {
- Attr child = makeAttr(parent, qname, value);
- parent.setAttributeNodeNS(child);
- return (child);
- }
-
- /**
- * Make a new DOM element.
- *
- * @param element Any element in the target document for the new element.
- * @param qname The qname of the new element.
- * @return The new element.
- */
- public static Element makeElement(Element element, QName qname) {
- return element.getOwnerDocument()
- .createElementNS(qname.getNamespaceURI(), qnameToString(qname));
- }
-
- /**
- * Make a new DOM text.
- *
- * @param element Any element in the target document for the new text.
- * @param content The content of the new text.
- * @return The new text.
- */
- public static Text makeText(Element element, String content) {
- return element.getOwnerDocument().createTextNode(content);
- }
-
- /**
- * Make a new DOM comment.
- *
- * @param element Any element in the target document for the new comment.
- * @param content The content of the new comment.
- * @return The new comment.
- */
- public static Comment makeComment(Element element, String content) {
- return element.getOwnerDocument().createComment(content);
- }
-
- /**
- * Make a new DOM attribute.
- *
- * @param element Any element in the target document for the new attribute.
- * @param qname The qname of the new attribute.
- * @param value The attribute's value.
- * @return The new attribute.
- */
- public static Attr makeAttr(Element element, QName qname, String value) {
- Attr attr = element.getOwnerDocument()
- .createAttributeNS(qname.getNamespaceURI(), qnameToString(qname));
- attr.setValue(value);
- return attr;
- }
-
- private static String qnameToString(QName qname) {
- String localPart = qname.getLocalPart();
- String prefix = qname.getPrefix();
- return
- (XMLConstants.DEFAULT_NS_PREFIX.equals(prefix))
- ? localPart
- : prefix + ":" + localPart;
- }
}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnAuthority.java b/src/com/google/enterprise/secmgr/config/AuthnAuthority.java
deleted file mode 100644
index 64599aa..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnAuthority.java
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Maps;
-import com.google.enterprise.secmgr.common.SecurityManagerUtil;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-
-import java.lang.reflect.Type;
-import java.net.URI;
-import java.util.Map;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * An authentication authority describes an authority that validates credentials.
- */
-@ThreadSafe
-@ParametersAreNonnullByDefault
-public class AuthnAuthority {
- @GuardedBy("itself")
- @Nonnull static final Map<URI, AuthnAuthority> AUTHORITIES = Maps.newHashMap();
-
- @Nonnull private final URI uri;
-
- private AuthnAuthority(URI uri) {
- this.uri = uri;
- }
-
- /**
- * Makes an authority.
- *
- * @param uri The URI for this authority.
- * @return The unique authority with that URI, creating it if necessary.
- * @throws IllegalArgumentException if the URI is invalid.
- */
- @CheckReturnValue
- @Nonnull
- public static AuthnAuthority make(URI uri) {
- checkUri(uri);
- AuthnAuthority authority;
- synchronized (AUTHORITIES) {
- authority = AUTHORITIES.get(uri);
- if (authority == null) {
- authority = new AuthnAuthority(uri);
- AUTHORITIES.put(uri, authority);
- }
- }
- return authority;
- }
-
- private static void checkUri(URI uri) {
- Preconditions.checkNotNull(uri);
- Preconditions.checkArgument(uri.isAbsolute());
- Preconditions.checkArgument(!uri.isOpaque());
- Preconditions.checkArgument(uri.getQuery() == null);
- Preconditions.checkArgument(uri.getFragment() == null);
- }
-
- static AuthnAuthority make(String configName) {
- return make(SecurityManagerUtil.smUriBuilder().addSegment(configName).build());
- }
-
- @VisibleForTesting
- public static AuthnAuthority make() {
- return make(SecurityManagerUtil.smUriBuilder().addRandomSegment(16).build());
- }
-
- /**
- * Gets a globally-unique URI for this authority.
- *
- * @return The authority's URI.
- */
- @CheckReturnValue
- @Nonnull
- public URI getUri() {
- return uri;
- }
-
- /**
- * Gets a globally-unique name for this authority. Equivalent to
- * {@code getUri().toString()}.
- *
- * @return The authority's name.
- */
- @CheckReturnValue
- @Nonnull
- public String getName() {
- return uri.toString();
- }
-
- /**
- * Gets an authority given its URI.
- *
- * @param uri The URI of the authority to find.
- * @return The corresponding authority, or {@code null} if no authority has that URI.
- */
- @CheckReturnValue
- @Nullable
- public static AuthnAuthority lookupByUri(URI uri) {
- checkUri(uri);
- synchronized (AUTHORITIES) {
- return AUTHORITIES.get(uri);
- }
- }
-
- /**
- * Gets an authority given its name.
- *
- * @param name The name of the authority to find.
- * @return The corresponding authority, or {@code null} if no authority has that name.
- */
- @CheckReturnValue
- @Nullable
- public static AuthnAuthority lookupByName(String name) {
- return lookupByUri(URI.create(name));
- }
-
- /**
- * Gets an authority given its name.
- *
- * @param name The name of the authority to find.
- * @return The corresponding authority.
- * @throw IllegalArgumentException if no such authority.
- */
- @CheckReturnValue
- @Nonnull
- public static AuthnAuthority getByName(String name) {
- AuthnAuthority authority = lookupByName(name);
- if (authority == null) {
- throw new IllegalArgumentException("No authority of this name: " + name);
- }
- return authority;
- }
-
- @VisibleForTesting
- public static void clearAuthorities() {
- synchronized (AUTHORITIES) {
- AUTHORITIES.clear();
- }
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof AuthnAuthority)) { return false; }
- AuthnAuthority other = (AuthnAuthority) object;
- return getUri().equals(other.getUri());
- }
-
- @Override
- public int hashCode() {
- return getUri().hashCode();
- }
-
- @Override
- public String toString() {
- return getName();
- }
-
- /**
- * Gets a predicate that is true for an authority with a given URI.
- *
- * @param uri The authority URI to test for.
- * @return The predicate corresponding to the name.
- */
- @CheckReturnValue
- @Nonnull
- public static Predicate<AuthnAuthority> getUriPredicate(final URI uri) {
- return new Predicate<AuthnAuthority>() {
- public boolean apply(AuthnAuthority authority) {
- return uri.equals(authority.getUri());
- }
- };
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(AuthnAuthority.class, new LocalTypeAdapter());
- }
-
- private static final class LocalTypeAdapter
- implements JsonSerializer<AuthnAuthority>, JsonDeserializer<AuthnAuthority> {
- LocalTypeAdapter() {
- }
-
- @Override
- public JsonElement serialize(AuthnAuthority value, Type type,
- JsonSerializationContext context) {
- return context.serialize(value.getName(), String.class);
- }
-
- @Override
- public AuthnAuthority deserialize(JsonElement elt, Type type,
- JsonDeserializationContext context) {
- String string = context.deserialize(elt, String.class);
- return make(URI.create(string));
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechBasic.java b/src/com/google/enterprise/secmgr/config/AuthnMechBasic.java
deleted file mode 100644
index 462b8cb..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechBasic.java
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of an HTTP Basic authentication mechanism.
- */
-@Immutable
-public final class AuthnMechBasic extends AuthnMechanism {
-
- public static final String TYPE_NAME = "Basic";
- private static final long DEFAULT_TRUST_DURATION = 20 * 60 * 1000; // 20 mins
-
- private final String sampleUrl;
- private final long trustDuration;
-
- /**
- * Make a new HTTP Basic mechanism.
- *
- * @param sampleUrl A sample URL that requires HTTP Basic authentication.
- * @param trustDuration The number of milliseconds for which successfully
- * verified credentials are trusted. This must be a non-negative number.
- * @return A new mechanism with the given elements.
- */
- public static AuthnMechBasic make(String name, String sampleUrl, long trustDuration) {
- return new AuthnMechBasic(name, sampleUrl, trustDuration);
- }
-
- /**
- * Make a new HTTP Basic mechanism with a default trust duration.
- *
- * @param sampleUrl A sample URL that requires HTTP Basic authentication.
- * @return A new mechanism with the given elements.
- */
- public static AuthnMechBasic make(String name, String sampleUrl) {
- return make(name, sampleUrl, getDefaultTrustDuration());
- }
-
- private AuthnMechBasic(String name, String sampleUrl, long trustDuration) {
- super(name);
- this.sampleUrl = checkString(sampleUrl);
- this.trustDuration = checkTrustDuration(trustDuration);
- }
-
- /**
- * Make a new unconfigured HTTP Basic mechanism.
- */
- public static AuthnMechBasic makeEmpty() {
- return new AuthnMechBasic();
- }
-
- private AuthnMechBasic() {
- super();
- this.sampleUrl = null;
- this.trustDuration = getDefaultTrustDuration();
- }
-
- @Override
- public String getTypeName() {
- return TYPE_NAME;
- }
-
- /**
- * Get the default trust-duration value.
- */
- public static long getDefaultTrustDuration() {
- return DEFAULT_TRUST_DURATION;
- }
-
- @Override
- public List<CredentialTransform> getCredentialTransforms() {
- return ImmutableList.of(
- CredentialTransform.make(
- CredentialTypeSet.PRINCIPAL_AND_PASSWORD,
- CredentialTypeSet.VERIFIED_PRINCIPAL_AND_PASSWORD));
- }
-
- @Override
- public AuthnMechanism copyWithNewName(String name) {
- return make(name, getSampleUrl(), getTrustDuration());
- }
-
- @Override
- public String getSampleUrl() {
- return sampleUrl;
- }
-
- @Override
- public long getTrustDuration() {
- return trustDuration;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof AuthnMechBasic)) { return false; }
- AuthnMechBasic mech = (AuthnMechBasic) object;
- return super.equals(mech)
- && Objects.equal(getSampleUrl(), mech.getSampleUrl())
- && Objects.equal(getTrustDuration(), mech.getTrustDuration());
- }
-
- @Override
- public int hashCode() {
- return super.hashCode(getSampleUrl(), getTrustDuration());
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(AuthnMechBasic.class,
- ProxyTypeAdapter.make(AuthnMechBasic.class, LocalProxy.class));
- }
-
- private static final class LocalProxy extends MechanismProxy<AuthnMechBasic> {
- String sampleUrl;
- long trustDuration = DEFAULT_TRUST_DURATION;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(AuthnMechBasic mechanism) {
- super(mechanism);
- sampleUrl = mechanism.getSampleUrl();
- trustDuration = mechanism.getTrustDuration();
- }
-
- @Override
- public AuthnMechBasic build() {
- return make(name, sampleUrl, trustDuration);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechClient.java b/src/com/google/enterprise/secmgr/config/AuthnMechClient.java
deleted file mode 100644
index 3dd7c29..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechClient.java
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of a client certificate authentication mechanism.
- */
-@Immutable
-public final class AuthnMechClient extends AuthnMechanism {
-
- public static final String TYPE_NAME = "X509Client";
- private static final long DEFAULT_TRUST_DURATION = 20 * 60 * 1000; // 20 mins
-
- /**
- * Make a new ClientAuth mechanism.
- */
- public static AuthnMechClient make(String name) {
- return new AuthnMechClient(name);
- }
-
- private AuthnMechClient(String name) {
- super(name);
- }
-
- /**
- * Make a new unconfigured ClientAuth mechanism.
- */
- public static AuthnMechClient makeEmpty() {
- return new AuthnMechClient();
- }
-
- private AuthnMechClient() {
- super();
- }
-
- @Override
- public String getTypeName() {
- return TYPE_NAME;
- }
-
- /**
- * Get the default trust-duration value.
- */
- public static long getDefaultTrustDuration() {
- return DEFAULT_TRUST_DURATION;
- }
-
- @Override
- public List<CredentialTransform> getCredentialTransforms() {
- return ImmutableList.of(
- CredentialTransform.make(CredentialTypeSet.NONE, CredentialTypeSet.VERIFIED_PRINCIPAL));
- }
-
- @Override
- public AuthnMechanism copyWithNewName(String name) {
- return make(name);
- }
-
- @Override
- public boolean equals(Object object) {
- return (object instanceof AuthnMechClient);
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(TYPE_NAME);
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(AuthnMechClient.class,
- ProxyTypeAdapter.make(AuthnMechClient.class, LocalProxy.class));
- }
-
- private static final class LocalProxy extends MechanismProxy<AuthnMechClient> {
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(AuthnMechClient mechanism) {
- super(mechanism);
- }
-
- @Override
- public AuthnMechClient build() {
- return make(name);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechConnector.java b/src/com/google/enterprise/secmgr/config/AuthnMechConnector.java
deleted file mode 100644
index eb87fe2..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechConnector.java
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of a connector authentication mechanism.
- */
-@Immutable
-public final class AuthnMechConnector extends AuthnMechanism {
-
- public static final String TYPE_NAME = "Connector";
- private static final long DEFAULT_TRUST_DURATION = 20 * 60 * 1000; // 20 mins
-
- private final String connectorName;
- private final boolean doGroupLookupOnly;
- private final long trustDuration;
-
- /**
- * Makes a new connector mechanism.
- *
- * @param name The name for the new mechanism.
- * @param connectorName The name of the connector to use.
- * @param doGroupLookupOnly To do only groups lookup and not authentication.
- * @param trustDuration The number of milliseconds for which successfully
- * verified credentials are trusted. This must be a non-negative number.
- * @return A new mechanism with the given elements.
- */
- public static AuthnMechConnector make(String name, String connectorName,
- boolean doGroupLookupOnly, long trustDuration) {
- return new AuthnMechConnector(name, connectorName, doGroupLookupOnly, trustDuration);
- }
-
- /**
- * Makes a new connector mechanism with a default trust duration.
- *
- * @param name The name for the new mechanism.
- * @param connectorName The name of the connector to use.
- * @param doGroupLookupOnly To do only groups lookup and not authentication.
- * @return A new mechanism with the given elements.
- */
- public static AuthnMechConnector make(String name, String connectorName,
- boolean doGroupLookupOnly) {
- return make(name, connectorName, doGroupLookupOnly, getDefaultTrustDuration());
- }
-
- private AuthnMechConnector(String name, String connectorName, boolean doGroupLookupOnly,
- long trustDuration) {
- super(name);
- this.connectorName = checkString(connectorName);
- this.doGroupLookupOnly = doGroupLookupOnly;
- this.trustDuration = checkTrustDuration(trustDuration);
- }
-
- /**
- * Makes a new unconfigured connector mechanism.
- */
- public static AuthnMechConnector makeEmpty() {
- return new AuthnMechConnector();
- }
-
- private AuthnMechConnector() {
- super();
- this.connectorName = null;
- this.doGroupLookupOnly = false;
- this.trustDuration = getDefaultTrustDuration();
- }
-
- @Override
- public String getTypeName() {
- return TYPE_NAME;
- }
-
- /**
- * Does this connector implement group lookup but not verification?
- *
- * @return True only if so.
- */
- public boolean doGroupLookupOnly() {
- return doGroupLookupOnly;
- }
-
- /**
- * Gets the default trust-duration value.
- */
- public static long getDefaultTrustDuration() {
- return DEFAULT_TRUST_DURATION;
- }
-
- @Override
- public List<CredentialTransform> getCredentialTransforms() {
- return ImmutableList.of(
- doGroupLookupOnly()
- ? CredentialTransform.make(
- CredentialTypeSet.VERIFIED_PRINCIPAL,
- CredentialTypeSet.VERIFIED_GROUPS)
- : CredentialTransform.make(
- CredentialTypeSet.PRINCIPAL_AND_PASSWORD,
- CredentialTypeSet.VERIFIED_PRINCIPAL_PASSWORD_AND_GROUPS));
- }
-
- @Override
- public AuthnMechanism copyWithNewName(String name) {
- return make(name, getConnectorName(), doGroupLookupOnly(), getTrustDuration());
- }
-
- @Override
- public long getTrustDuration() {
- return trustDuration;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof AuthnMechConnector)) { return false; }
- AuthnMechConnector mech = (AuthnMechConnector) object;
- return super.equals(mech)
- && Objects.equal(getConnectorName(), mech.getConnectorName())
- && Objects.equal(getTrustDuration(), mech.getTrustDuration());
- }
-
- @Override
- public int hashCode() {
- return super.hashCode(getConnectorName(), getTrustDuration());
- }
-
- /**
- * Gets the name of this connector.
- *
- * @return The connector name, never null or empty.
- */
- public String getConnectorName() {
- return connectorName;
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(AuthnMechConnector.class,
- ProxyTypeAdapter.make(AuthnMechConnector.class, LocalProxy.class));
- }
-
- private static final class LocalProxy extends MechanismProxy<AuthnMechConnector> {
- String connectorName;
- boolean doGroupLookupOnly;
- long trustDuration = DEFAULT_TRUST_DURATION;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(AuthnMechConnector mechanism) {
- super(mechanism);
- connectorName = mechanism.getConnectorName();
- doGroupLookupOnly = mechanism.doGroupLookupOnly();
- trustDuration = mechanism.getTrustDuration();
- }
-
- @Override
- public AuthnMechConnector build() {
- return make(name, connectorName, doGroupLookupOnly, trustDuration);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechForm.java b/src/com/google/enterprise/secmgr/config/AuthnMechForm.java
deleted file mode 100644
index 7244b94..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechForm.java
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of a form SSO authentication mechanism.
- */
-@Immutable
-public final class AuthnMechForm extends AuthnMechanism {
-
- public static final String TYPE_NAME = "CookieBased";
- private static final long DEFAULT_TRUST_DURATION = 5 * 60 * 1000; // 5 minutes
-
- private final String sampleUrl;
- private final long trustDuration;
-
- private AuthnMechForm(String name, String sampleUrl, long trustDuration) {
- super(name);
- this.sampleUrl = checkStringOrNull(sampleUrl);
- this.trustDuration = checkTrustDuration(trustDuration);
- }
-
- /**
- * Makes a new HTTP form mechanism.
- *
- * @param name A name for the new mechanism.
- * @param sampleUrl A sample URL that is protected by form authentication.
- * @param trustDuration The number of milliseconds that successfully
- * verified credentials are trusted. This must be a non-negative number.
- * @return A new mechanism with the given elements.
- */
- public static AuthnMechForm make(String name, String sampleUrl, long trustDuration) {
- return new AuthnMechForm(name, sampleUrl, trustDuration);
- }
-
- /**
- * Makes a new HTTP form mechanism with a default trust duration.
- *
- * @param name A name for the new mechanism.
- * @param sampleUrl A sample URL that is protected by form authentication.
- * @return A new mechanism with the given elements.
- */
- public static AuthnMechForm make(String name, String sampleUrl) {
- return make(name, sampleUrl, getDefaultTrustDuration());
- }
-
- /**
- * Make a new unconfigured HTTP form mechanism.
- */
- public static AuthnMechForm makeEmpty() {
- return new AuthnMechForm();
- }
-
- private AuthnMechForm() {
- super();
- this.sampleUrl = null;
- this.trustDuration = getDefaultTrustDuration();
- }
-
- @Override
- public String getTypeName() {
- return TYPE_NAME;
- }
-
- /**
- * Get the default trust-duration value.
- */
- public static long getDefaultTrustDuration() {
- return DEFAULT_TRUST_DURATION;
- }
-
- @Override
- public List<CredentialTransform> getCredentialTransforms() {
- return ImmutableList.of(
- CredentialTransform.make(
- CredentialTypeSet.PRINCIPAL_AND_PASSWORD,
- CredentialTypeSet.VERIFIED_PRINCIPAL_AND_PASSWORD),
- CredentialTransform.make(CredentialTypeSet.COOKIES, CredentialTypeSet.VERIFIED_PRINCIPAL),
- CredentialTransform.make(CredentialTypeSet.COOKIES, CredentialTypeSet.VERIFIED_ALIASES),
- CredentialTransform.make(CredentialTypeSet.COOKIES, CredentialTypeSet.VERIFIED_GROUPS));
- }
-
- @Override
- public AuthnMechanism copyWithNewName(String name) {
- return make(name, getSampleUrl(), getTrustDuration());
- }
-
- @Override
- public String getSampleUrl() {
- return sampleUrl;
- }
-
- @Override
- public long getTrustDuration() {
- return trustDuration;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof AuthnMechForm)) { return false; }
- AuthnMechForm mech = (AuthnMechForm) object;
- return super.equals(mech)
- && Objects.equal(getSampleUrl(), mech.getSampleUrl())
- && Objects.equal(getTrustDuration(), mech.getTrustDuration());
- }
-
- @Override
- public int hashCode() {
- return super.hashCode(getSampleUrl(), getTrustDuration());
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(AuthnMechForm.class,
- ProxyTypeAdapter.make(AuthnMechForm.class, LocalProxy.class));
- }
-
- private static final class LocalProxy extends MechanismProxy<AuthnMechForm> {
- String sampleUrl;
- long trustDuration = DEFAULT_TRUST_DURATION;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(AuthnMechForm mechanism) {
- super(mechanism);
- sampleUrl = mechanism.getSampleUrl();
- trustDuration = mechanism.getTrustDuration();
- }
-
- @Override
- public AuthnMechForm build() {
- return make(name, sampleUrl, trustDuration);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechKerberos.java b/src/com/google/enterprise/secmgr/config/AuthnMechKerberos.java
deleted file mode 100644
index 16e7f0f..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechKerberos.java
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of a kerberos authentication mechanism.
- */
-@Immutable
-public final class AuthnMechKerberos extends AuthnMechanism {
-
- public static final String TYPE_NAME = "Kerberos";
- private static final long DEFAULT_TRUST_DURATION = 5 * 60 * 1000; // 5 minutes
-
- /**
- * Make a new Kerberos mechanism.
- */
- public static AuthnMechKerberos make(String name) {
- return new AuthnMechKerberos(name);
- }
-
- private AuthnMechKerberos(String name) {
- super(name);
- }
-
- /**
- * Make a new unconfigured Kerberos mechanism.
- */
- public static AuthnMechKerberos makeEmpty() {
- return new AuthnMechKerberos();
- }
-
- private AuthnMechKerberos() {
- super();
- }
-
- @Override
- public String getTypeName() {
- return TYPE_NAME;
- }
-
- /**
- * TODO(jiajia): do we need to place the kerb ticket expiration time here?
- */
- @Override
- public long getTrustDuration() {
- return getDefaultTrustDuration();
- }
-
- /**
- * Get the default trust-duration value.
- */
- public static long getDefaultTrustDuration() {
- return DEFAULT_TRUST_DURATION;
- }
-
- @Override
- public List<CredentialTransform> getCredentialTransforms() {
- return ImmutableList.of(
- CredentialTransform.make(CredentialTypeSet.NONE, CredentialTypeSet.VERIFIED_PRINCIPAL));
- }
-
- @Override
- public AuthnMechanism copyWithNewName(String name) {
- return make(name);
- }
-
- @Override
- public boolean equals(Object object) {
- return (object instanceof AuthnMechKerberos);
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(TYPE_NAME);
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(AuthnMechKerberos.class,
- ProxyTypeAdapter.make(AuthnMechKerberos.class, LocalProxy.class));
- }
-
- private static final class LocalProxy extends MechanismProxy<AuthnMechKerberos> {
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(AuthnMechKerberos mechanism) {
- super(mechanism);
- }
-
- @Override
- public AuthnMechKerberos build() {
- return make(name);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechLdap.java b/src/com/google/enterprise/secmgr/config/AuthnMechLdap.java
deleted file mode 100644
index 3b2a781..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechLdap.java
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-/**
- * LDAP configuration.
- */
-public final class AuthnMechLdap extends AuthnMechanism {
-
- public static final String TYPE_NAME = "LDAP";
- private static final long DEFAULT_TRUST_DURATION = 20 * 60 * 1000; // 20 mins
-
- private final boolean enableAuthn;
- private final boolean enableGroupLookup;
-
- private final String hostport;
- private final String bindDn;
- private final String password;
- private final String searchBase;
- private final String userSearchFilter;
- private final String groupSearchFilter;
- private final int sslSupport;
- private final int supportedAuthMethods;
-
- private final long trustDuration;
-
- /**
- * Make a new LDAP AuthN mechanism.
- *
- * @param hostport a hostname and port of the format "HOST:PORT"
- * @param bindDn the DN to bind with, or empty for anonymous binding
- * @param password the password to bind with, or empty for anonymous binding
- * @param searchBase component of DN common to all users
- * @param userSearchFilter filter used to search for user
- * @param groupSearchFilter filter used to find user's groups
- * @param sslSupport the type of SSL to use
- * @param supportedAuthMethods the auth methods supported by the server
- * @param enableAuthn whether this mech is enabled for authentication
- * @param enableGroupLookup whether this mech is enabled for doing groups lookup
- * @param trustDuration The number of milliseconds for which successfully
- * verified credentials are trusted. This must be a non-negative number.
- * @return A new mechanism with the given configuration
- */
- public static AuthnMechLdap make(String name, String hostport, String bindDn,
- String password, String searchBase,
- String userSearchFilter, String groupSearchFilter,
- int sslSupport, int supportedAuthMethods,
- boolean enableAuthn, boolean enableGroupLookup,
- long trustDuration) {
- return new AuthnMechLdap(name, hostport, bindDn, password, searchBase,
- userSearchFilter, groupSearchFilter, sslSupport,
- supportedAuthMethods, enableAuthn, enableGroupLookup,
- trustDuration);
- }
-
- private AuthnMechLdap(String name, String hostport, String bindDn, String password,
- String searchBase, String userSearchFilter, String groupSearchFilter,
- int sslSupport, int supportedAuthMethods, boolean enableAuthn,
- boolean enableGroupLookup, long trustDuration) {
- super(name);
- this.hostport = hostport;
- this.bindDn = bindDn;
- this.password = password;
- this.searchBase = searchBase;
- this.userSearchFilter = userSearchFilter;
- this.groupSearchFilter = groupSearchFilter;
- this.sslSupport = sslSupport;
- this.supportedAuthMethods = supportedAuthMethods;
- this.enableAuthn = enableAuthn;
- this.enableGroupLookup = enableGroupLookup;
- this.trustDuration = trustDuration;
- }
-
- public static AuthnMechLdap makeEmpty() {
- return new AuthnMechLdap();
- }
-
- private AuthnMechLdap() {
- super();
- this.hostport = null;
- this.bindDn = null;
- this.password = null;
- this.searchBase = null;
- this.userSearchFilter = null;
- this.groupSearchFilter = null;
- this.sslSupport = 0;
- this.supportedAuthMethods = 0;
- this.enableAuthn = false;
- this.enableGroupLookup = false;
- this.trustDuration = getDefaultTrustDuration();
- }
-
- public String getHostport() {
- return hostport;
- }
-
- public String getBindDn() {
- return bindDn;
- }
-
- public String getPassword() {
- return password;
- }
-
- public String getSearchBase() {
- return searchBase;
- }
-
- public String getUserSearchFilter() {
- return userSearchFilter;
- }
-
- public String getGroupSearchFilter() {
- return groupSearchFilter;
- }
-
- public int getSslSupport() {
- return sslSupport;
- }
-
- public int getSupportedAuthMethods() {
- return supportedAuthMethods;
- }
-
- public boolean isEnableAuthn() {
- return enableAuthn;
- }
-
- public boolean isEnableGroupLookup() {
- return enableGroupLookup;
- }
-
- @Override
- public long getTrustDuration() {
- return trustDuration;
- }
-
- @Override
- public String getTypeName() {
- return TYPE_NAME;
- }
-
- @Override
- public List<CredentialTransform> getCredentialTransforms() {
- ImmutableList.Builder<CredentialTransform> builder = ImmutableList.builder();
- if (isEnableAuthn()) {
- builder.add(
- CredentialTransform.make(
- CredentialTypeSet.PRINCIPAL_AND_PASSWORD,
- CredentialTypeSet.VERIFIED_PRINCIPAL_AND_PASSWORD));
- }
- if (isEnableGroupLookup()) {
- builder.add(
- CredentialTransform.make(
- CredentialTypeSet.VERIFIED_PRINCIPAL,
- CredentialTypeSet.VERIFIED_GROUPS));
- }
- return builder.build();
- }
-
- @Override
- public AuthnMechanism copyWithNewName(String name) {
- return make(name, getHostport(), getBindDn(), getPassword(), getSearchBase(),
- getUserSearchFilter(), getGroupSearchFilter(), getSslSupport(), getSupportedAuthMethods(),
- isEnableAuthn(), isEnableGroupLookup(), getTrustDuration());
- }
-
- public static long getDefaultTrustDuration() {
- return DEFAULT_TRUST_DURATION;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof AuthnMechLdap)) { return false; }
- AuthnMechLdap mech = (AuthnMechLdap) object;
- return super.equals(mech)
- && Objects.equal(getHostport(), mech.getHostport())
- && Objects.equal(getBindDn(), mech.getBindDn())
- && Objects.equal(getPassword(), mech.getPassword())
- && Objects.equal(getSearchBase(), mech.getSearchBase())
- && Objects.equal(getUserSearchFilter(), mech.getUserSearchFilter())
- && Objects.equal(getGroupSearchFilter(), mech.getGroupSearchFilter())
- && Objects.equal(getSslSupport(), mech.getSslSupport())
- && Objects.equal(getSupportedAuthMethods(), mech.getSupportedAuthMethods())
- && Objects.equal(isEnableAuthn(), mech.isEnableAuthn())
- && Objects.equal(isEnableGroupLookup(), mech.isEnableGroupLookup()
- && Objects.equal(getTrustDuration(), mech.getTrustDuration()));
- }
-
- @Override
- public int hashCode() {
- return super.hashCode(getHostport(), getBindDn(), getPassword(), getSearchBase(),
- getUserSearchFilter(), getGroupSearchFilter(), getSslSupport(), getSupportedAuthMethods(),
- isEnableAuthn(), isEnableGroupLookup(), getTrustDuration());
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(AuthnMechLdap.class,
- ProxyTypeAdapter.make(AuthnMechLdap.class, LocalProxy.class));
- }
-
- private static final class LocalProxy extends MechanismProxy<AuthnMechLdap> {
- boolean enableAuthn;
- boolean enableGroupLookup;
- String hostport;
- String bindDn;
- String password;
- String searchBase;
- String userSearchFilter;
- String groupSearchFilter;
- int sslSupport;
- int supportedAuthMethods;
- long trustDuration = DEFAULT_TRUST_DURATION;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(AuthnMechLdap mechanism) {
- super(mechanism);
- hostport = mechanism.getHostport();
- bindDn = mechanism.getBindDn();
- password = mechanism.getPassword();
- searchBase = mechanism.getSearchBase();
- userSearchFilter = mechanism.getUserSearchFilter();
- groupSearchFilter = mechanism.getGroupSearchFilter();
- sslSupport = mechanism.getSslSupport();
- supportedAuthMethods = mechanism.getSupportedAuthMethods();
- enableAuthn = mechanism.isEnableAuthn();
- enableGroupLookup = mechanism.isEnableGroupLookup();
- trustDuration = mechanism.getTrustDuration();
- }
-
- @Override
- public AuthnMechLdap build() {
- return make(name, hostport, bindDn, password, searchBase, userSearchFilter, groupSearchFilter,
- sslSupport, supportedAuthMethods, enableAuthn, enableGroupLookup, trustDuration);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechNtlm.java b/src/com/google/enterprise/secmgr/config/AuthnMechNtlm.java
deleted file mode 100644
index 035810b..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechNtlm.java
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of an NTLM authentication mechanism.
- */
-@Immutable
-public final class AuthnMechNtlm extends AuthnMechanism {
-
- public static final String TYPE_NAME = "NTLM";
- private static final long DEFAULT_TRUST_DURATION = 20 * 60 * 1000; // 20 mins
-
- private final String sampleUrl;
- private final long trustDuration;
-
- /**
- * Make a new NTLM mechanism.
- *
- * @param sampleUrl A sample URL that requires NTLM authentication.
- * @param trustDuration The number of milliseconds that successfully
- * verified credentials are trusted. This must be a non-negative number.
- * @return A new mechanism with the given elements.
- */
- public static AuthnMechNtlm make(String name, String sampleUrl, long trustDuration) {
- return new AuthnMechNtlm(name, sampleUrl, trustDuration);
- }
-
- /**
- * Make a new NTLM mechanism with a default trust duration.
- *
- * @param sampleUrl A sample URL that requires NTLM authentication.
- * @return A new mechanism with the given elements.
- */
- public static AuthnMechNtlm make(String name, String sampleUrl) {
- return make(name, sampleUrl, getDefaultTrustDuration());
- }
-
- private AuthnMechNtlm(String name, String sampleUrl, long trustDuration) {
- super(name);
- this.sampleUrl = checkString(sampleUrl);
- this.trustDuration = checkTrustDuration(trustDuration);
- }
-
- /**
- * Make a new unconfigured NTLM mechanism.
- */
- public static AuthnMechNtlm makeEmpty() {
- return new AuthnMechNtlm();
- }
-
- private AuthnMechNtlm() {
- super();
- this.sampleUrl = null;
- this.trustDuration = getDefaultTrustDuration();
- }
-
- @Override
- public String getTypeName() {
- return TYPE_NAME;
- }
-
- /**
- * Get the default trust-duration value.
- */
- public static long getDefaultTrustDuration() {
- return DEFAULT_TRUST_DURATION;
- }
-
- @Override
- public List<CredentialTransform> getCredentialTransforms() {
- return ImmutableList.of(
- CredentialTransform.make(
- CredentialTypeSet.PRINCIPAL_AND_PASSWORD,
- CredentialTypeSet.VERIFIED_PRINCIPAL_AND_PASSWORD));
- }
-
- @Override
- public AuthnMechanism copyWithNewName(String name) {
- return make(name, getSampleUrl(), getTrustDuration());
- }
-
- @Override
- public String getSampleUrl() {
- return sampleUrl;
- }
-
- @Override
- public long getTrustDuration() {
- return trustDuration;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof AuthnMechNtlm)) { return false; }
- AuthnMechNtlm mech = (AuthnMechNtlm) object;
- return super.equals(mech)
- && Objects.equal(getSampleUrl(), mech.getSampleUrl())
- && Objects.equal(getTrustDuration(), mech.getTrustDuration());
- }
-
- @Override
- public int hashCode() {
- return super.hashCode(getSampleUrl(), getTrustDuration());
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(AuthnMechNtlm.class,
- ProxyTypeAdapter.make(AuthnMechNtlm.class, LocalProxy.class));
- }
-
- private static final class LocalProxy extends MechanismProxy<AuthnMechNtlm> {
- String sampleUrl;
- long trustDuration = DEFAULT_TRUST_DURATION;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(AuthnMechNtlm mechanism) {
- super(mechanism);
- sampleUrl = mechanism.getSampleUrl();
- trustDuration = mechanism.getTrustDuration();
- }
-
- @Override
- public AuthnMechNtlm build() {
- return make(name, sampleUrl, trustDuration);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechSaml.java b/src/com/google/enterprise/secmgr/config/AuthnMechSaml.java
deleted file mode 100644
index 529624c..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechSaml.java
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of a SAML authentication mechanism.
- */
-@Immutable
-public final class AuthnMechSaml extends AuthnMechanism {
-
- public static final String TYPE_NAME = "SAML";
-
- private final String entityId;
-
- public static AuthnMechSaml make(String name, String entityId) {
- return new AuthnMechSaml(name, entityId);
- }
-
- private AuthnMechSaml(String name, String entityId) {
- super(name);
- this.entityId = checkString(entityId);
- }
-
- public static AuthnMechSaml makeEmpty() {
- return new AuthnMechSaml();
- }
-
- private AuthnMechSaml() {
- super();
- this.entityId = null;
- }
-
- @Override
- public String getTypeName() {
- return TYPE_NAME;
- }
-
- @Override
- public List<CredentialTransform> getCredentialTransforms() {
- return ImmutableList.of(
- CredentialTransform.make(CredentialTypeSet.NONE, CredentialTypeSet.VERIFIED_PRINCIPAL));
- }
-
- @Override
- public AuthnMechanism copyWithNewName(String name) {
- return make(name, getEntityId());
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof AuthnMechSaml)) { return false; }
- AuthnMechSaml mech = (AuthnMechSaml) object;
- return super.equals(mech)
- && Objects.equal(entityId, mech.getEntityId());
- }
-
- @Override
- public int hashCode() {
- return super.hashCode(entityId);
- }
-
- /**
- * Get the SAML entity ID for this authority. This ID is used as a key when
- * looking up SAML metadata that describes the authority.
- *
- * @return The SAML entity ID as a string, never null or empty, normally a URI.
- */
- public String getEntityId() {
- return entityId;
- }
-
- public static final Predicate<AuthnMechanism> SAML_PREDICATE = new Predicate<AuthnMechanism>() {
- public boolean apply(AuthnMechanism config) {
- return (config instanceof AuthnMechSaml);
- }
- };
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(AuthnMechSaml.class,
- ProxyTypeAdapter.make(AuthnMechSaml.class, LocalProxy.class));
- }
-
- private static final class LocalProxy extends MechanismProxy<AuthnMechSaml> {
- String entityId;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(AuthnMechSaml mechanism) {
- super(mechanism);
- entityId = mechanism.getEntityId();
- }
-
- @Override
- public AuthnMechSaml build() {
- return make(name, entityId);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechSampleUrl.java b/src/com/google/enterprise/secmgr/config/AuthnMechSampleUrl.java
deleted file mode 100644
index a9a99be..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechSampleUrl.java
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of a sample-URL check authentication mechanism.
- */
-@Immutable
-public final class AuthnMechSampleUrl extends AuthnMechanism {
-
- public static final String TYPE_NAME = "SampleUrlCheck";
- public static final String DEFAULT_RETURN_URL_PARAMETER = "returnPath";
- private static final long DEFAULT_TRUST_DURATION = 5 * 60 * 1000; // five minutes
-
- private final String sampleUrl;
- private final String redirectUrl;
- private final String returnUrlParameter;
- private final long trustDuration;
-
- /**
- * Make a new sample-URL cookie mechanism.
- *
- * @param sampleUrl A sample URL that requires cookie authentication.
- * @param redirectUrl A URL to redirect the user agent to in order to get the cookie(s).
- * @param trustDuration The number of milliseconds that successfully
- * verified credentials are trusted. This must be a non-negative number.
- * @return A new mechanism with the given elements.
- */
- public static AuthnMechSampleUrl make(String name, String sampleUrl, String redirectUrl,
- String returnUrlParameter, long trustDuration) {
- return new AuthnMechSampleUrl(name, sampleUrl, redirectUrl, returnUrlParameter, trustDuration);
- }
-
- /**
- * Make a new sample-URL cookie mechanism with a default trust duration.
- *
- * @param sampleUrl A sample URL that requires cookie authentication.
- * @param redirectUrl A URL to redirect the user agent to in order to get the cookie(s).
- * @return A new mechanism with the given elements.
- */
- public static AuthnMechSampleUrl make(String name, String sampleUrl, String redirectUrl) {
- return make(name, sampleUrl, redirectUrl, getDefaultReturnUrlParameter(),
- getDefaultTrustDuration());
- }
-
- private AuthnMechSampleUrl(String name, String sampleUrl, String redirectUrl,
- String returnUrlParameter, long trustDuration) {
- super(name);
- this.sampleUrl = checkStringOrNull(sampleUrl);
- this.redirectUrl = checkStringOrNull(redirectUrl);
- this.returnUrlParameter = checkStringOrNull(returnUrlParameter);
- this.trustDuration = checkTrustDuration(trustDuration);
- }
-
- /**
- * Make a new unconfigured sample-URL cookie mechanism.
- */
- public static AuthnMechSampleUrl makeEmpty() {
- return new AuthnMechSampleUrl();
- }
-
- private AuthnMechSampleUrl() {
- super();
- this.sampleUrl = null;
- this.redirectUrl = null;
- this.returnUrlParameter = getDefaultReturnUrlParameter();
- this.trustDuration = getDefaultTrustDuration();
- }
-
- @Override
- public String getTypeName() {
- return TYPE_NAME;
- }
-
- public static String getDefaultReturnUrlParameter() {
- return DEFAULT_RETURN_URL_PARAMETER;
- }
-
- /**
- * Get the default trust-duration value.
- */
- public static long getDefaultTrustDuration() {
- return DEFAULT_TRUST_DURATION;
- }
-
- @Override
- public List<CredentialTransform> getCredentialTransforms() {
- if (redirectUrl != null) {
- return ImmutableList.of();
- }
- return ImmutableList.of(
- CredentialTransform.make(CredentialTypeSet.COOKIES, CredentialTypeSet.VERIFIED_PRINCIPAL),
- CredentialTransform.make(CredentialTypeSet.COOKIES, CredentialTypeSet.VERIFIED_ALIASES),
- CredentialTransform.make(CredentialTypeSet.COOKIES, CredentialTypeSet.VERIFIED_GROUPS));
- }
-
- @Override
- public AuthnMechanism copyWithNewName(String name) {
- return make(name, getSampleUrl(), getRedirectUrl(), getReturnUrlParameter(),
- getTrustDuration());
- }
-
- @Override
- public String getSampleUrl() {
- return sampleUrl;
- }
-
- /**
- * Gets the redirect URL associated with this authority.
- *
- * @return The redirect URL as a string, or {@code null} if none exists.
- */
- public String getRedirectUrl() {
- return redirectUrl;
- }
-
- /**
- * Gets the return-URL parameter associated with this authority.
- *
- * This is the name of the request/CGI param we set on an outbound redirect,
- * which tells the server on the receiving end of the redirect where to
- * redirect back to once it's done.
- *
- * The default value for this is {@code "returnPath"}.
- *
- * @return The return url parameter string, or {@code null} for default.
- */
- public String getReturnUrlParameter() {
- return returnUrlParameter;
- }
-
- @Override
- public long getTrustDuration() {
- return trustDuration;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof AuthnMechSampleUrl)) { return false; }
- AuthnMechSampleUrl mech = (AuthnMechSampleUrl) object;
- return super.equals(mech)
- && Objects.equal(getSampleUrl(), mech.getSampleUrl())
- && Objects.equal(getRedirectUrl(), mech.getRedirectUrl())
- && Objects.equal(getReturnUrlParameter(), mech.getReturnUrlParameter())
- && Objects.equal(getTrustDuration(), mech.getTrustDuration());
- }
-
- @Override
- public int hashCode() {
- return super.hashCode(getSampleUrl(), getRedirectUrl(), getReturnUrlParameter(),
- getTrustDuration());
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(AuthnMechSampleUrl.class,
- ProxyTypeAdapter.make(AuthnMechSampleUrl.class, LocalProxy.class));
- }
-
- private static final class LocalProxy extends MechanismProxy<AuthnMechSampleUrl> {
- String sampleUrl;
- String redirectUrl;
- String returnUrlParameter = DEFAULT_RETURN_URL_PARAMETER;
- long trustDuration = DEFAULT_TRUST_DURATION;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(AuthnMechSampleUrl mechanism) {
- super(mechanism);
- sampleUrl = mechanism.getSampleUrl();
- redirectUrl = mechanism.getRedirectUrl();
- returnUrlParameter = mechanism.getReturnUrlParameter();
- trustDuration = mechanism.getTrustDuration();
- }
-
- @Override
- public AuthnMechSampleUrl build() {
- return make(name, sampleUrl, redirectUrl, returnUrlParameter, trustDuration);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechanism.java b/src/com/google/enterprise/secmgr/config/AuthnMechanism.java
deleted file mode 100644
index 5754e81..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechanism.java
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.List;
-import java.util.Locale;
-import java.util.regex.Pattern;
-
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * The configuration of an authentication mechanism. This is the base class for
- * all mechanisms; individual mechanisms inherit from here.
- */
-@ThreadSafe
-public abstract class AuthnMechanism {
- private static final int CONFIG_NAME_MAX_LENGTH = 200;
- private static final Pattern CONFIG_NAME_PATTERN
- = Pattern.compile("^[a-zA-Z0-9_][a-zA-Z0-9_-]*$");
-
- private final String name;
- private final AuthnAuthority authority;
-
- protected AuthnMechanism() {
- name = null;
- authority = AuthnAuthority.make();
- }
-
- protected AuthnMechanism(String name) {
- // TODO(cph): eliminate name == null once all callers supply real names.
- // Right now the only callers with name == null are unit tests.
- this.name = name;
- if (name == null) {
- authority = AuthnAuthority.make();
- } else {
- Preconditions.checkArgument(isValidConfigName(name), "Invalid mechanism name: %s", name);
- authority = AuthnAuthority.make(name);
- }
- }
-
- /**
- * Is a given string a valid name for a mechanism or credential group? A
- * valid name is between 1 and 200 characters and consists only of ASCII
- * alphanumerics, the underscore character, and the hyphen character. The
- * first character may not be a hyphen.
- *
- * @param name The string to test for validity.
- * @return True only if the string is valid.
- */
- public static boolean isValidConfigName(String name) {
- return name != null
- && !name.isEmpty()
- && name.length() <= CONFIG_NAME_MAX_LENGTH
- && CONFIG_NAME_PATTERN.matcher(name).matches();
- }
-
- /**
- * Check a string argument that's allowed to be null. Disallows empty
- * strings. May return a modified string; e.g. may run .trim() on the
- * argument.
- *
- * @param string The string to check.
- * @return A checked string that is possibly different from the argument.
- * @throws IllegalArgumentException if the input string is empty.
- */
- protected static String checkStringOrNull(String string) {
- Preconditions.checkArgument(string == null || !string.isEmpty());
- return string;
- }
-
- /**
- * Check a string argument. Disallows null and empty strings. May return a
- * modified string; e.g. may run .trim() on the argument.
- *
- * @param string The string to check.
- * @return A checked string that is possibly different from the argument.
- * @throws IllegalArgumentException if the input string is null or empty.
- */
- protected static String checkString(String string) {
- Preconditions.checkArgument(string != null && !string.isEmpty());
- return string;
- }
-
- /**
- * Check a URL string argument. Disallows null and non-well-formed strings.
- * May return a modified string; e.g. may run .trim() on the argument.
- *
- * @param string The URL string to check.
- * @return A checked URL string that is possibly different from the argument.
- * @throws IllegalArgumentException if the input string is null or not well formed.
- */
- protected static String checkUrlString(String string) {
- try {
- return (new URL(checkString(string))).toString();
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Check a trust-duration argument.
- *
- * @param trustDuration The trust-duration argument to check.
- * @return A checked value.
- * @throws IllegalArgumentException if the argument is invalid.
- */
- protected static long checkTrustDuration(long trustDuration) {
- Preconditions.checkArgument(trustDuration >= 0);
- return trustDuration;
- }
-
- /**
- * Get the type name of the mechanism.
- *
- * @return The type name, never null or empty.
- */
- public abstract String getTypeName();
-
- /**
- * @return An immutable list of the transformations this mechanism implements.
- */
- public abstract List<CredentialTransform> getCredentialTransforms();
-
- /**
- * Can this mechanism use ULF credentials?
- */
- public boolean canUseUlfCredentials() {
- return Iterables.any(getCredentialTransforms(),
- new Predicate<CredentialTransform>() {
- public boolean apply(CredentialTransform credentialTransform) {
- CredentialTypeSet inputs = credentialTransform.getInputs();
- return !inputs.getAreVerified()
- && inputs.getElements().containsAll(
- CredentialTypeSet.PRINCIPAL_AND_PASSWORD.getElements());
- }
- });
- }
-
- /**
- * Return a copy of the current mechanism, with a given name.
- *
- * @param name The new name.
- * @return A copy of the current mechanism with the new name.
- */
- public abstract AuthnMechanism copyWithNewName(String name);
-
- /**
- * @return This mechanism's name.
- */
- public String getName() {
- return name;
- }
-
- /**
- * @return This mechanism's authority.
- */
- public AuthnAuthority getAuthority() {
- return authority;
- }
-
- public static Function<AuthnMechanism, AuthnAuthority> getAuthorityFunction() {
- return AUTHORITY_FUNCTION;
- }
-
- private static final Function<AuthnMechanism, AuthnAuthority> AUTHORITY_FUNCTION
- = new Function<AuthnMechanism, AuthnAuthority>() {
- @Override
- public AuthnAuthority apply(AuthnMechanism mechanism) {
- return mechanism.getAuthority();
- }
- };
-
- /**
- * A sample URL to GET for credential verification.
- *
- * @return The mechanism's sample URL as a string, or null if none.
- */
- public String getSampleUrl() {
- throw new UnsupportedOperationException();
- }
-
- /**
- * For how many milliseconds does this mechanism trust newly-verified
- * credentials?
- *
- * @return The number of milliseconds, always a non-negative number.
- */
- public long getTrustDuration() {
- throw new UnsupportedOperationException();
- }
-
- protected boolean equals(AuthnMechanism other) {
- return getName() == null
- || other.getName() == null
- || getName().equalsIgnoreCase(other.getName());
- }
-
- protected int hashCode(Object... objects) {
- Object[] copy = new Object[objects.length + 1];
- copy[0] = (getName() != null)
- ? getName().toLowerCase(Locale.US)
- : null;
- for (int i = 0; i < objects.length; i += 1) {
- copy[i + 1] = objects[i];
- }
- return Objects.hashCode(copy);
- }
-
- @Override
- public String toString() {
- return ConfigSingleton.getGson().toJson(this);
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(AuthnMechanism.class,
- TypeAdapters.dispatch(
- ImmutableList.of(
- AuthnMechBasic.class,
- AuthnMechClient.class,
- AuthnMechConnector.class,
- AuthnMechForm.class,
- AuthnMechKerberos.class,
- AuthnMechLdap.class,
- AuthnMechNtlm.class,
- AuthnMechSaml.class,
- AuthnMechSampleUrl.class)));
- }
-
- /** A base class for type proxies of sub-classes. */
- protected abstract static class MechanismProxy<T extends AuthnMechanism>
- implements TypeProxy<T> {
- public String name;
-
- protected MechanismProxy() {
- }
-
- protected MechanismProxy(AuthnMechanism mechanism) {
- name = mechanism.getName();
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthzMechanism.java b/src/com/google/enterprise/secmgr/config/AuthzMechanism.java
deleted file mode 100644
index fd80ce1..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthzMechanism.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-/**
- * @author meghna@google.com (Meghna Dhar)
- */
-public enum AuthzMechanism {
- CACHE,
- CONNECTOR,
- DENY,
- HEADREQUEST,
- POLICY,
- SAML,
-}
diff --git a/src/com/google/enterprise/secmgr/config/ConfigCodec.java b/src/com/google/enterprise/secmgr/config/ConfigCodec.java
deleted file mode 100644
index f0aaa6a..0000000
--- a/src/com/google/enterprise/secmgr/config/ConfigCodec.java
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2008 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-
-/**
- * A base class for implementing a configuration encode/decode class.
- */
-public abstract class ConfigCodec {
-
- /**
- * Decode a configuration from a string.
- *
- * @param string The string to decode.
- * @return A configuration.
- * @throws IOException if there are errors while reading the configuration.
- * @throws ConfigException if the configuration is malformed.
- */
- public SecurityManagerConfig readConfig(String string)
- throws IOException, ConfigException {
- return readConfig(new StringReader(string));
- }
-
- /**
- * Encode a configuration as a string.
- *
- * @param config The configuration to be encoded.
- * @return The encoded string.
- * @throws IOException if there are errors while writing the configuration.
- */
- public String configToString(SecurityManagerConfig config) throws IOException {
- Writer writer = new StringWriter();
- writeConfig(config, writer);
- return writer.toString();
- }
-
- /**
- * Read and decode a configuration from a given source.
- *
- * @param reader The source to read the encoded configuration from.
- * @return A configuration.
- * @throws IOException if there are errors while reading the configuration.
- * @throws ConfigException if the configuration is malformed.
- */
- public SecurityManagerConfig readConfig(Reader reader)
- throws IOException, ConfigException {
- SecurityManagerConfig config = readConfigInternal(reader);
- guaranteeValidConfig(config);
- return config;
- }
-
- /**
- * Read and decode a configuration from a given file.
- *
- * @param file The file to read the encoded configuration from.
- * @return A configuration.
- * @throws IOException if there are errors while reading the configuration.
- * @throws ConfigException if the configuration is malformed.
- */
- public SecurityManagerConfig readConfig(File file)
- throws IOException, ConfigException {
- Reader reader = new FileReader(file);
- try {
- return readConfig(reader);
- } finally {
- reader.close();
- }
- }
-
- protected abstract SecurityManagerConfig readConfigInternal(Reader reader)
- throws IOException, ConfigException;
-
- /**
- * Encode and write a configuration to a given sink.
- *
- * @param config The configuration to be encoded.
- * @param writer The sink to write the encoded configuration to.
- * @throws IOException if there are errors while writing the configuration.
- */
- public void writeConfig(SecurityManagerConfig config, Writer writer) throws IOException {
- guaranteeValidConfig(config);
- writeConfigInternal(config, writer);
- }
-
- protected abstract void writeConfigInternal(SecurityManagerConfig config, Writer writer)
- throws IOException;
-
- private void guaranteeValidConfig(SecurityManagerConfig config) {
- if (!isValidConfig(config)) {
- throw new IllegalStateException("Config is not valid: " + config);
- }
- }
-
- /**
- * A valid config must contain a "default" group and that group must require a
- * username, be non-optional, and non-empty. This in turn ensures that a saml
- * assertion from the security manager will always contain a username which
- * can in turn be used when creating policy ACLs.
- *
- * TODO(martincochran): ensure that EFE gets the right username and/or that
- * the correct saml subject is generated by the security manager.
- */
- private boolean isValidConfig(SecurityManagerConfig config) {
-
- return true;
- /* TODO(kstillson): I'm disabling this check. It was added to address
- * to address the concern that PVI assignment may not be stable- specifically,
- * user1 has a forms auth cookie before any interaction with the GSA, if the
- * default CG does not insist on requires-username, then CG will be satisfied
- * but no username is set, so the PVI could come from somewhere else (e.g.
- * kerberos). However, user2 has no cookie, so they get a ULF, and the PVI
- * is set by their forms login. That is a problem, however, this solution
- * is too drastic, and eliminates numerous valid use-cases (such as a sec-mgr
- * that does nothing but a single forms-auth CG that doesn't need a username).
- * So We're going to have to find a more subtle solution to the original
- * problem.
-
- if (config.isEmpty()) {
- return true;
- }
- boolean defaultGroupEmpty = false;
- boolean someGroupNonEmpty = false;
-
- for (CredentialsGroup group : config) {
- if ("default".equalsIgnoreCase(group.getName())) {
- if (!group.getRequiresUsername()) {
- return false;
- }
- if (group.getIsOptional()) {
- return false;
- }
- if (!group.getElements().isEmpty()) {
- return true;
- }
- }
- if (!group.getElements().isEmpty()) {
- someGroupNonEmpty = true;
- }
- }
- return !someGroupNonEmpty;
- */
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/ConfigException.java b/src/com/google/enterprise/secmgr/config/ConfigException.java
deleted file mode 100644
index 89418ea..0000000
--- a/src/com/google/enterprise/secmgr/config/ConfigException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-/**
- * An exception that's thrown when a {@link ConfigCodec} has trouble parsing a
- * configuration string.
- */
-public class ConfigException extends Exception {
-
- public ConfigException(String message) { super(message); }
-
- public ConfigException(Throwable e) { super(e); }
-
- public ConfigException(String message, Throwable e) { super(message, e); }
-}
diff --git a/src/com/google/enterprise/secmgr/config/ConfigModule.java b/src/com/google/enterprise/secmgr/config/ConfigModule.java
deleted file mode 100644
index fd55612..0000000
--- a/src/com/google/enterprise/secmgr/config/ConfigModule.java
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.gson.GsonBuilder;
-/*import com.google.inject.AbstractModule;
-import com.google.inject.name.Names;*/
-
-/**
- * Guice configuration for this package.
- */
-public final class ConfigModule /*extends AbstractModule*/ {
-
- private final String configFilename;
-
- public ConfigModule(String configFilename) {
- this.configFilename = configFilename;
- }
-
-/* @Override
- protected void configure() {
- bind(ConfigCodec.class).to(JsonConfig.class);
- bind(ConfigSingleton.class);
- bind(FlexAuthorizer.class).to(FlexAuthorizerImpl.class);
- bindConstant()
- .annotatedWith(Names.named("configFile"))
- .to(configFilename);
- requestStaticInjection(ConfigSingleton.class);
- }*/
-
- public static void registerTypeAdapters(GsonBuilder builder) {
- AuthnAuthority.registerTypeAdapters(builder);
- AuthnMechBasic.registerTypeAdapters(builder);
- AuthnMechClient.registerTypeAdapters(builder);
- AuthnMechConnector.registerTypeAdapters(builder);
- AuthnMechForm.registerTypeAdapters(builder);
- AuthnMechKerberos.registerTypeAdapters(builder);
- AuthnMechLdap.registerTypeAdapters(builder);
- AuthnMechNtlm.registerTypeAdapters(builder);
- AuthnMechSaml.registerTypeAdapters(builder);
- AuthnMechSampleUrl.registerTypeAdapters(builder);
- AuthnMechanism.registerTypeAdapters(builder);
- ConfigParams.registerTypeAdapters(builder);
- ConnMgrInfo.registerTypeAdapters(builder);
- CredentialGroup.registerTypeAdapters(builder);
- FlexAuthorizerImpl.registerTypeAdapters(builder);
- FlexAuthzRoutingTableEntry.registerTypeAdapters(builder);
- FlexAuthzRule.registerTypeAdapters(builder);
- ParamName.registerTypeAdapters(builder);
- SecurityManagerConfig.registerTypeAdapters(builder);
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/ConfigParams.java b/src/com/google/enterprise/secmgr/config/ConfigParams.java
deleted file mode 100644
index c8a8aae..0000000
--- a/src/com/google/enterprise/secmgr/config/ConfigParams.java
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-
-import java.lang.reflect.Type;
-import java.util.EnumSet;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * An generalized configuration-parameters implementation. This can store any
- * named parameter, of any type.
- *
- * @see ParamName
- */
-@Immutable
-public final class ConfigParams {
-
- private final ImmutableMap<ParamName, Object> map;
-
- private ConfigParams(ImmutableMap<ParamName, Object> map) {
- this.map = map;
- }
-
- /**
- * Gets the set of keys.
- *
- * @return The keys.
- */
- public static EnumSet<ParamName> keySet() {
- return EnumSet.allOf(ParamName.class);
- }
-
- /**
- * Gets the value of a parameter.
- *
- * @param key The name of the parameter to retrieve.
- * @return The value of the parameter.
- */
- public Object get(ParamName key) {
- return map.get(key);
- }
-
- /**
- * Gets the value of a parameter, casting it to a given type.
- *
- * @param key The name of the parameter to retrieve.
- * @param valueClass The class to cast the value to.
- * @return The value of the parameter.
- * @throws IllegalArgumentException if <code>valueClass</code> isn't
- * assignable from the parameter's value.
- */
- public <T> T get(ParamName key, Class<T> valueClass) {
- Preconditions.checkArgument(valueClass.isAssignableFrom(key.getValueClass()));
- return valueClass.cast(get(key));
- }
-
- /**
- * Gets a default set of configuration parameters.
- *
- * @return The default set.
- */
- public static ConfigParams makeDefault() {
- return builder().build();
- }
-
- /**
- * Gets a new configuration-parameters builder.
- *
- * @return A new builder.
- */
- public static Builder builder() {
- return new Builder(null);
- }
-
- /**
- * Gets a new configuration-parameters builder initialized with defaults.
- *
- * @param defaultValues A set of configuration parameters to use as defaults.
- * @return A new builder.
- */
- public static Builder builder(ConfigParams defaultValues) {
- Preconditions.checkNotNull(defaultValues);
- return new Builder(defaultValues);
- }
-
- /**
- * A builder factory for configuration parameters.
- */
- public static final class Builder {
- private final ConfigParams defaultValues;
- private final ImmutableMap.Builder<ParamName, Object> mapBuilder;
- private final EnumSet<ParamName> unseen;
-
- private Builder(ConfigParams defaultValues) {
- this.defaultValues = defaultValues;
- mapBuilder = ImmutableMap.builder();
- unseen = EnumSet.allOf(ParamName.class);
- }
-
- /**
- * Set the value of a parameter.
- *
- * @param key The parameter's name.
- * @param value The parameter's value.
- * @return This builder, for programming convenience.
- * @throws IllegalArgumentException if the value isn't valid for this parameter.
- */
- public Builder put(ParamName key, Object value) {
- Preconditions.checkArgument(key.isValidValue(value));
- mapBuilder.put(key, value);
- unseen.remove(key);
- return this;
- }
-
- /**
- * @return The completed parameters object.
- */
- public ConfigParams build() {
- for (ParamName key : unseen) {
- mapBuilder.put(key,
- (defaultValues == null)
- ? key.getDefaultValue()
- : defaultValues.get(key));
- }
- return new ConfigParams(mapBuilder.build());
- }
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof ConfigParams)) { return false; }
- ConfigParams other = (ConfigParams) object;
- for (ParamName key : keySet()) {
- if (!get(key).equals(other.get(key))) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public int hashCode() {
- EnumSet<ParamName> keys = keySet();
- Object[] values = new Object[keys.size()];
- int i = 0;
- for (ParamName key : keys) {
- values[i++] = get(key);
- }
- return Objects.hashCode(values);
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(ConfigParams.class, new LocalTypeAdapter());
- }
-
- static final class LocalTypeAdapter
- implements JsonSerializer<ConfigParams>, JsonDeserializer<ConfigParams> {
- LocalTypeAdapter() {
- }
-
- @Override
- public JsonElement serialize(ConfigParams params, Type type, JsonSerializationContext context) {
- JsonObject jo = new JsonObject();
- for (ParamName key : ConfigParams.keySet()) {
- jo.add(key.toString(), context.serialize(params.get(key), key.getValueClass()));
- }
- return jo;
- }
-
- @Override
- public ConfigParams deserialize(JsonElement src, Type type,
- JsonDeserializationContext context) {
- JsonObject jo = src.getAsJsonObject();
- ConfigParams.Builder builder = ConfigParams.builder();
- for (ParamName key : ConfigParams.keySet()) {
- JsonElement je = jo.get(key.toString());
- if (je != null) {
- builder.put(key, context.deserialize(je, key.getValueClass()));
- }
- }
- return builder.build();
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/ConfigSingleton.java b/src/com/google/enterprise/secmgr/config/ConfigSingleton.java
index 8853daa..d445578 100644
--- a/src/com/google/enterprise/secmgr/config/ConfigSingleton.java
+++ b/src/com/google/enterprise/secmgr/config/ConfigSingleton.java
@@ -16,22 +16,11 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.enterprise.secmgr.common.FileUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Key;
-import com.google.inject.Singleton;
-import com.google.inject.TypeLiteral;
-import com.google.inject.name.Named;
-import java.io.File;
-import java.io.IOException;
import java.util.Observable;
import java.util.Observer;
-import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.concurrent.GuardedBy;
@@ -40,14 +29,11 @@
/**
* A singleton class to access configured parameters.
*/
-@Singleton
@ThreadSafe
public class ConfigSingleton {
private static final Logger LOGGER = Logger.getLogger(ConfigSingleton.class.getName());
- @Inject private static Injector injector;
- @Inject private static ConfigSingleton instance;
- @GuardedBy("class") private static SecurityManagerConfig configOverride = null;
+ private static ConfigSingleton instance;
@GuardedBy("class") private static Gson gson;
private static final LocalObservable observable = new LocalObservable();
@@ -58,58 +44,16 @@
}
}
- private final ConfigCodec configCodec;
- private final String configFilename;
- /** The modification time of the configuration file when last read. */
- @GuardedBy("this") private long configTime;
- /** The parsed configuration file. */
- @GuardedBy("this") private SecurityManagerConfig config;
-
- @Inject
- private ConfigSingleton(ConfigCodec configCodec, @Named("configFile") String configFilename) {
- Preconditions.checkNotNull(configCodec);
- Preconditions.checkArgument(!Strings.isNullOrEmpty(configFilename));
- this.configCodec = configCodec;
- this.configFilename = configFilename;
+ private ConfigSingleton() {
resetInternal();
}
- /**
- * @return The application's Guice injector.
- */
- public static Injector getInjector() {
- return injector;
- }
-
- /**
- * A convenience method that invokes the injector.
- *
- * @param clazz The class to instantiate.
- * @return An instance of the given class.
- */
- public static <T> T getInstance(Class<T> clazz) {
- return injector.getInstance(clazz);
- }
-
- /**
- * A convenience method that invokes the injector.
- *
- * @param type The type to instantiate.
- * @return An instance of the given type.
- */
- public static <T> T getInstance(TypeLiteral<T> type) {
- return injector.getInstance(Key.get(type));
- }
-
@VisibleForTesting
public static synchronized void reset() {
- configOverride = null;
instance.resetInternal();
}
private synchronized void resetInternal() {
- configTime = 0;
- config = null;
}
/**
@@ -147,115 +91,4 @@
Preconditions.checkNotNull(gson);
return gson;
}
-
- /**
- * @return The current configuration.
- * @throws IOException if there are I/O errors reading the configuration.
- */
- public static synchronized SecurityManagerConfig getConfig()
- throws IOException {
- return (configOverride != null) ? configOverride : getConfigNoOverride();
- }
-
- @VisibleForTesting
- public static synchronized SecurityManagerConfig getConfigNoOverride()
- throws IOException {
- return instance.getConfigInternal();
- }
-
- @VisibleForTesting
- public static synchronized void setConfig(SecurityManagerConfig config) {
- configOverride = config;
- setChanged();
- }
-
- private synchronized SecurityManagerConfig getConfigInternal()
- throws IOException {
- File file = FileUtil.getContextFile(configFilename);
- // Check the config file's mod time; if it hasn't changed since the last
- // successful read, use the cached value. Otherwise, try reading the config
- // file. Go around the loop until the mod time before the read and the mod
- // time after the read are the same. This detects changes to the file
- // during the read.
- while (true) {
- long time = file.lastModified();
- if (time == 0) {
- throw new IOException("No such file: " + file);
- }
- if (time == configTime) {
- break;
- }
- try {
- config = configCodec.readConfig(file);
- } catch (ConfigException e) {
- LOGGER.log(Level.SEVERE, "Error parsing config file. Returning default config.", e);
- config = SecurityManagerConfig.makeDefault();
- }
- configTime = time;
- LOGGER.fine("Config:\n" + config);
- observable.setChanged();
- }
- observable.notifyObservers();
- return config;
- }
-
- /** @see SecurityManagerConfig#getAclGroupsFilename */
- public static String getAclGroupsFilename() throws IOException {
- return getConfig().getAclGroupsFilename();
- }
-
- /** @see SecurityManagerConfig#getAclUrlsFilename */
- public static String getAclUrlsFilename() throws IOException {
- return getConfig().getAclUrlsFilename();
- }
-
- /** @see SecurityManagerConfig#getCertificateAuthoritiesFilename */
- public static String getCertificateAuthoritiesFilename() throws IOException {
- return getConfig().getCertificateAuthoritiesFilename();
- }
-
- /** @see SecurityManagerConfig#getConnectorManagerUrls */
- public static Iterable<String> getConnectorManagerUrls() throws IOException {
- return getConfig().getConnectorManagerUrls();
- }
-
- /** @see SecurityManagerConfig#getDenyRulesFilename */
- public static String getDenyRulesFilename() throws IOException {
- return getConfig().getDenyRulesFilename();
- }
-
- /** @see SecurityManagerConfig#getGlobalBatchRequestTimeout */
- public static Float getGlobalBatchRequestTimeout() throws IOException {
- return getConfig().getGlobalBatchRequestTimeout();
- }
-
- /** @see SecurityManagerConfig#getGlobalSingleRequestTimeout */
- public static Float getGlobalSingleRequestTimeout() throws IOException {
- return getConfig().getGlobalSingleRequestTimeout();
- }
-
- /** @see SecurityManagerConfig#getSamlMetadataFilename */
- public static String getSamlMetadataFilename() throws IOException {
- return getConfig().getSamlMetadataFilename();
- }
-
- /** @see SecurityManagerConfig#getServerCertificateFilename */
- public static String getServerCertificateFilename() throws IOException {
- return getConfig().getServerCertificateFilename();
- }
-
- /** @see SecurityManagerConfig#getSigningCertificateFilename */
- public static String getSigningCertificateFilename() throws IOException {
- return getConfig().getSigningCertificateFilename();
- }
-
- /** @see SecurityManagerConfig#getSigningKeyFilename */
- public static String getSigningKeyFilename() throws IOException {
- return getConfig().getSigningKeyFilename();
- }
-
- /** @see SecurityManagerConfig#getStunnelPort */
- public static int getStunnelPort() throws IOException {
- return getConfig().getStunnelPort();
- }
}
diff --git a/src/com/google/enterprise/secmgr/config/ConnMgrInfo.java b/src/com/google/enterprise/secmgr/config/ConnMgrInfo.java
deleted file mode 100644
index 74079eb..0000000
--- a/src/com/google/enterprise/secmgr/config/ConnMgrInfo.java
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A structure describing a set of configured connector managers.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class ConnMgrInfo {
-
- /**
- * A structure describing a single connector manager.
- */
- @Immutable
- @ParametersAreNonnullByDefault
- public static final class Entry {
- @Nonnull private final String name;
- @Nonnull private final String url;
-
- private Entry(String name, String url) {
- this.name = name;
- this.url = url;
- }
-
- /**
- * Makes a new connector-manager entry.
- *
- * @param name The name of the connector manager.
- * @param url The URL for the connector manager.
- * @return An entry containing the above information.
- */
- @Nonnull
- public static Entry make(String name, String url) {
- Preconditions.checkNotNull(name);
- Preconditions.checkNotNull(url);
- return new Entry(name, url);
- }
-
- /**
- * Gets the name of the connector manager represented by this entry.
- *
- * @return The connector-manager name.
- */
- @Nonnull
- public String getName() {
- return name;
- }
-
- /**
- * Gets the URL of the connector manager represented by this entry.
- *
- * @return The connector-manager URL as a string.
- */
- @Nonnull
- public String getUrl() {
- return url;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof Entry)) { return false; }
- Entry other = (Entry) object;
- return Objects.equal(getName(), other.getName())
- && Objects.equal(getUrl(), other.getUrl());
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(getName(), getUrl());
- }
-
- @Override
- public String toString() {
- return ConfigSingleton.getGson().toJson(this);
- }
- }
-
- @Nonnull private final ImmutableSet<Entry> entries;
-
- private ConnMgrInfo(ImmutableSet<Entry> entries) {
- this.entries = entries;
- }
-
- /**
- * Makes a new connector-manager info object.
- *
- * @param entries The per-connector-manager entries.
- * @return A new set with the given entries.
- */
- @Nonnull
- public static ConnMgrInfo make(Iterable<Entry> entries) {
- return new ConnMgrInfo(ImmutableSet.copyOf(entries));
- }
-
- /**
- * Gets the per-connector-manager entries for this object.
- *
- * @return The entries as an immutable set.
- */
- @Nonnull
- public ImmutableSet<Entry> getEntries() {
- return entries;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof ConnMgrInfo)) { return false; }
- ConnMgrInfo other = (ConnMgrInfo) object;
- return Objects.equal(getEntries(), other.getEntries());
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(getEntries());
- }
-
- @Override
- public String toString() {
- return ConfigSingleton.getGson().toJson(this);
- }
-
- /**
- * Decodes string-encoded connector-manager info.
- *
- * @param string The encoded info.
- * @return The decoded info.
- */
- public static ConnMgrInfo valueOf(String string) {
- return ConfigSingleton.getGson().fromJson(string, ConnMgrInfo.class);
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(new TypeToken<ImmutableSet<Entry>>() {}.getType(),
- TypeAdapters.immutableSet());
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/CredentialGroup.java b/src/com/google/enterprise/secmgr/config/CredentialGroup.java
deleted file mode 100644
index 200d447..0000000
--- a/src/com/google/enterprise/secmgr/config/CredentialGroup.java
+++ /dev/null
@@ -1,320 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-import java.util.Collection;
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-import javax.annotation.concurrent.NotThreadSafe;
-
-/**
- * A "credential group" is a set of authentication mechanisms that are defined
- * to share a common username and password.
- */
-@Immutable
-public class CredentialGroup {
-
- public static final String DEFAULT_NAME = "Default";
-
- private final String name;
- private final AuthnAuthority authority;
- private final String displayName;
- private final boolean requiresUsername; // Not satisfied until a username is known.
- private final boolean requiresPassword; // Not satisfied until a password is known.
- private final boolean isOptional; // Can be satisfied given blank username & password.
- private final ImmutableList<AuthnMechanism> mechanisms;
-
- private CredentialGroup(String name, String displayName, boolean requiresUsername,
- boolean requiresPassword, boolean isOptional, List<AuthnMechanism> mechanisms) {
- Preconditions.checkArgument(name != null && AuthnMechanism.isValidConfigName(name),
- "Invalid credential-group name: %s", name);
- this.name = name;
- authority = AuthnAuthority.make(name);
- this.displayName = (displayName != null) ? displayName : name;
- this.requiresUsername = requiresUsername;
- this.requiresPassword = requiresPassword;
- this.isOptional = isOptional;
- this.mechanisms = ImmutableList.copyOf(mechanisms);
- }
-
- /**
- * Get a credential-group builder.
- *
- * @param name The name of the group; used in ACLs.
- * @param displayName The name of the group as presented to end users.
- * @param requiresUsername Does the group require a verified username?
- * @param requiresPassword Does the group require a verified password?
- * @param isOptional False if the credentials for this group must be supplied.
- * @return A credential-group builder with given initial settings and no mechanisms.
- */
- public static Builder builder(String name, String displayName, boolean requiresUsername,
- boolean requiresPassword, boolean isOptional) {
- return new Builder(name, displayName, requiresUsername, requiresPassword, isOptional);
- }
-
- /**
- * Get a credential-group builder.
- *
- * @param group A credential group to get the initial settings from.
- * @return A credential-group builder initialized with the given credential group.
- */
- public static Builder builder(CredentialGroup group) {
- Builder newBuilder = new Builder(group.getName(), group.getDisplayName(),
- group.getRequiresUsername(), group.getRequiresPassword(), group.getIsOptional());
- newBuilder.addMechanisms(group.getMechanisms());
- return newBuilder;
- }
-
- /**
- * Get a credential-group builder.
- *
- * @return A credential-group builder with default initial settings and no mechanisms.
- */
- public static Builder builder() {
- return builder(DEFAULT_NAME, DEFAULT_NAME, true, false, false);
- }
-
- /**
- * A builder factor for credential-group instances.
- */
- @NotThreadSafe
- public static final class Builder {
-
- private String name;
- private String displayName;
- private boolean requiresUsername;
- private boolean requiresPassword;
- private boolean isOptional;
- private List<AuthnMechanism> mechanisms;
-
- private Builder(String name, String displayName, boolean requiresUsername,
- boolean requiresPassword, boolean isOptional) {
- this.name = name;
- this.displayName = displayName;
- this.requiresUsername = requiresUsername;
- this.requiresPassword = requiresPassword;
- this.isOptional = isOptional;
- this.mechanisms = Lists.newArrayList();
- }
-
- public String getName() {
- return name;
- }
-
- public Builder setName(String name) {
- this.name = name;
- return this;
- }
-
- public Builder setDisplayName(String displayName) {
- this.displayName = displayName;
- return this;
- }
-
- public Builder setRequiresUsername(boolean requiresUsername) {
- this.requiresUsername = requiresUsername;
- return this;
- }
-
- public Builder setRequiresPassword(boolean requiresPassword) {
- this.requiresPassword = requiresPassword;
- return this;
- }
-
- public Builder setIsOptional(boolean isOptional) {
- this.isOptional = isOptional;
- return this;
- }
-
- public List<AuthnMechanism> getMechanisms() {
- return mechanisms;
- }
-
- public Builder addMechanism(AuthnMechanism mechanism) {
- mechanisms.add(mechanism);
- return this;
- }
-
- public Builder addMechanism(int index, AuthnMechanism mechanism) {
- mechanisms.add(index, mechanism);
- return this;
- }
-
- public Builder addMechanisms(Collection<AuthnMechanism> mechanisms) {
- this.mechanisms.addAll(mechanisms);
- return this;
- }
-
- public AuthnMechanism findMechanism(String name) {
- for (AuthnMechanism mechanism : mechanisms) {
- if (name.equalsIgnoreCase(mechanism.getName())) {
- return mechanism;
- }
- }
- return null;
- }
-
- public Builder replaceMechanism(AuthnMechanism mechanism) {
- AuthnMechanism other = findMechanism(mechanism.getName());
- Preconditions.checkArgument(other != null,
- "No existing mechanism with this name: %s", mechanism.getName());
- mechanisms.remove(other);
- mechanisms.add(mechanism);
- return this;
- }
-
- public CredentialGroup build() {
- return new CredentialGroup(name, displayName, requiresUsername, requiresPassword, isOptional,
- mechanisms);
- }
- }
-
- public String getName() {
- return name;
- }
-
- public AuthnAuthority getAuthority() {
- return authority;
- }
-
- public String getDisplayName() {
- return displayName;
- }
-
- public ImmutableList<AuthnMechanism> getMechanisms() {
- return mechanisms;
- }
-
- public boolean hasMechanismOfType(Class<? extends AuthnMechanism> type) {
- for (AuthnMechanism mech : mechanisms) {
- if (type.isInstance(mech)) {
- return true;
- }
- }
- return false;
- }
-
- public boolean getRequiresUsername() {
- return requiresUsername;
- }
-
- public boolean getRequiresPassword() {
- return requiresPassword;
- }
-
- public boolean getIsOptional() {
- return isOptional;
- }
-
- @Override
- public String toString() {
- return ConfigSingleton.getGson().toJson(this);
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof CredentialGroup)) { return false; }
- CredentialGroup other = (CredentialGroup) object;
- return Objects.equal(name, other.name)
- && Objects.equal(displayName, other.displayName)
- && Objects.equal(requiresUsername, other.requiresUsername)
- && Objects.equal(requiresPassword, other.requiresPassword)
- && Objects.equal(isOptional, other.isOptional)
- && Objects.equal(mechanisms, other.mechanisms);
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(name, displayName, requiresUsername, requiresPassword, isOptional,
- mechanisms);
- }
-
- public boolean isDefault() {
- return DEFAULT_NAME.equalsIgnoreCase(name);
- }
-
- public boolean canUseUlfCredentials() {
- for (AuthnMechanism mech : mechanisms) {
- if (mech.canUseUlfCredentials()) {
- return true;
- }
- }
- return false;
- }
-
- public static final Predicate<CredentialGroup> DEFAULT_PREDICATE =
- new Predicate<CredentialGroup>() {
- public boolean apply(CredentialGroup credentialGroup) {
- return credentialGroup.isDefault();
- }
- };
-
- public static final Function<Builder, CredentialGroup> BUILD_FUNCTION =
- new Function<Builder, CredentialGroup>() {
- public CredentialGroup apply(Builder builder) {
- return builder.build();
- }
- };
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(CredentialGroup.class,
- ProxyTypeAdapter.make(CredentialGroup.class, LocalProxy.class));
- builder.registerTypeAdapter(new TypeToken<ImmutableList<AuthnMechanism>>() {}.getType(),
- TypeAdapters.immutableList());
- }
-
- private static final class LocalProxy implements TypeProxy<CredentialGroup> {
- String name;
- String displayName;
- boolean requiresUsername;
- boolean requiresPassword;
- boolean isOptional;
- ImmutableList<AuthnMechanism> mechanisms;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(CredentialGroup credentialGroup) {
- name = credentialGroup.name;
- displayName = credentialGroup.displayName;
- requiresUsername = credentialGroup.requiresUsername;
- requiresPassword = credentialGroup.requiresPassword;
- isOptional = credentialGroup.isOptional;
- mechanisms = credentialGroup.mechanisms;
- }
-
- @Override
- public CredentialGroup build() {
- return new CredentialGroup(name, displayName, requiresUsername, requiresPassword, isOptional,
- mechanisms);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/CredentialTransform.java b/src/com/google/enterprise/secmgr/config/CredentialTransform.java
deleted file mode 100644
index 8e580ff..0000000
--- a/src/com/google/enterprise/secmgr/config/CredentialTransform.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-/**
- * A model of a particular credential transform implemented by a mechanism.
- * For example, a typical transform accepts some credentials as inputs and
- * verifies them, returning mutually-verified credentials.
- */
-public final class CredentialTransform {
- private final CredentialTypeSet inputs;
- private final CredentialTypeSet outputs;
-
- private CredentialTransform(CredentialTypeSet inputs, CredentialTypeSet outputs) {
- this.inputs = inputs;
- this.outputs = outputs;
- }
-
- /**
- * Make a credential transform.
- *
- * @param inputs The inputs to the transform.
- * @param outputs The outputs from the transform.
- * @return A transform with the given inputs and outputs.
- */
- public static CredentialTransform make(CredentialTypeSet inputs, CredentialTypeSet outputs) {
- return new CredentialTransform(inputs, outputs);
- }
-
- /**
- * @return The inputs to this transform.
- */
- public CredentialTypeSet getInputs() {
- return inputs;
- }
-
- /**
- * @return The outputs from this transform.
- */
- public CredentialTypeSet getOutputs() {
- return outputs;
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/CredentialTypeName.java b/src/com/google/enterprise/secmgr/config/CredentialTypeName.java
deleted file mode 100644
index 6ae5146..0000000
--- a/src/com/google/enterprise/secmgr/config/CredentialTypeName.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-/**
- * A set of tokens identifying the possible credential types. Used by modeling
- * in preference to the classes that implement these types.
- */
-public enum CredentialTypeName {
- PRINCIPAL, PASSWORD, ALIASES, GROUPS, COOKIES, KERBEROS_TICKET, X509_CERTIFICATE;
-}
diff --git a/src/com/google/enterprise/secmgr/config/CredentialTypeSet.java b/src/com/google/enterprise/secmgr/config/CredentialTypeSet.java
deleted file mode 100644
index 3a10c5a..0000000
--- a/src/com/google/enterprise/secmgr/config/CredentialTypeSet.java
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-
-import java.util.Set;
-
-/**
- * A set of credential types, used as an input to or output from a credential
- * transform.
- */
-public class CredentialTypeSet {
- private final boolean areVerified;
- private final ImmutableSet<CredentialTypeName> elements;
-
- private CredentialTypeSet(boolean areVerified, ImmutableSet<CredentialTypeName> elements) {
- this.areVerified = areVerified;
- this.elements = elements;
- }
-
- /**
- * Make a credential-type set.
- *
- * @param areVerified True if the represented credentials are verified.
- * @param elements The credential types that are the elements of this set.
- * @return A credential-type set with those elements.
- */
- public static CredentialTypeSet make(boolean areVerified, Iterable<CredentialTypeName> elements) {
- return new CredentialTypeSet(areVerified, ImmutableSet.copyOf(elements));
- }
-
- /**
- * @return True if the credentials are mutually verified.
- */
- public boolean getAreVerified() {
- return areVerified;
- }
-
- /**
- * @return An immutable set of the credential types that are the elements of
- * this set.
- */
- public Set<CredentialTypeName> getElements() {
- return elements;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof CredentialTypeSet)) { return false; }
- CredentialTypeSet other = (CredentialTypeSet) object;
- return Objects.equal(getAreVerified(), other.getAreVerified())
- && Objects.equal(getElements(), other.getElements());
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(getAreVerified(), getElements());
- }
-
- public static final CredentialTypeSet NONE =
- make(false, ImmutableList.<CredentialTypeName>of());
-
- public static final CredentialTypeSet COOKIES =
- make(false, ImmutableList.of(CredentialTypeName.COOKIES));
-
- public static final CredentialTypeSet PRINCIPAL_AND_PASSWORD =
- make(false, ImmutableList.of(CredentialTypeName.PRINCIPAL, CredentialTypeName.PASSWORD));
-
- public static final CredentialTypeSet VERIFIED_PRINCIPAL_AND_PASSWORD =
- make(true, ImmutableList.of(CredentialTypeName.PRINCIPAL, CredentialTypeName.PASSWORD));
-
- public static final CredentialTypeSet VERIFIED_PRINCIPAL_PASSWORD_AND_GROUPS =
- make(true, ImmutableList.of(CredentialTypeName.PRINCIPAL, CredentialTypeName.PASSWORD,
- CredentialTypeName.GROUPS));
-
- public static final CredentialTypeSet VERIFIED_PRINCIPAL =
- make(true, ImmutableList.of(CredentialTypeName.PRINCIPAL));
-
- public static final CredentialTypeSet VERIFIED_ALIASES =
- make(true, ImmutableList.of(CredentialTypeName.ALIASES));
-
- public static final CredentialTypeSet VERIFIED_GROUPS =
- make(true, ImmutableList.of(CredentialTypeName.GROUPS));
-}
diff --git a/src/com/google/enterprise/secmgr/config/FlexAuthorizer.java b/src/com/google/enterprise/secmgr/config/FlexAuthorizer.java
deleted file mode 100644
index 0597a0c..0000000
--- a/src/com/google/enterprise/secmgr/config/FlexAuthorizer.java
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Interface for Flexible Authorization.
- *
- * This class provides accessors and mutators for the Authz Routing Table and
- * the Authz Rules Table. Each entry in the routing table is uniquely defined
- * by a UUID. Each rule in the rule table is uniquely defined by its display
- * name.
- *
- * @author meghna@google.com (Meghna Dhar)
- */
-public interface FlexAuthorizer {
-
- /**
- * Add an entry to the routing table.
- *
- * @param order The priority order for the entry; the entry will
- * be stored at that position, and all subsequent entries have their order
- * increased by one.
- * @param entry The entry to be added.
- * @throws IllegalArgumentException if the new entry refers to a rule that's
- * not in the rule table, or if the order is less than zero or greater
- * than the number of entries in the routing table.
- */
- public void addToRoutingTable(int order, FlexAuthzRoutingTableEntry entry);
-
- /**
- * Add an entry at the end of the routing table.
- *
- * @param entry The entry to be added.
- * @throws IllegalArgumentException if the new entry refers to a rule that's
- * not in the rule table.
- */
- public void addToRoutingTable(FlexAuthzRoutingTableEntry entry);
-
- /**
- * Delete an entry from the routing table.
- *
- * @param uuid The UUID of the entry to delete.
- * @throws IllegalArgumentException if there's no entry in the table with that UUID.
- */
- public void deleteFromRoutingTable(UUID uuid);
-
- /**
- * Update an entry in the routing table.
- *
- * @param order The priority order for the entry; the entry will
- * be stored at that position, and all subsequent entries have their order
- * increased by one.
- * @param entry The new entry; must have the same UUID as an existing entry.
- * @throws IllegalArgumentException if the entry refers to a rule that's not
- * in the rule table, or if the entry's UUID doesn't match an existing
- * entry.
- */
- public void updateRoutingTable(int order, FlexAuthzRoutingTableEntry entry);
-
- /**
- * Given a UUID, get the corresponding entry from the routing table.
- *
- * @param uuid The UUID to search for.
- * @return The corresponding entry, or null if there's none.
- */
- public FlexAuthzRoutingTableEntry getFromRoutingTable(UUID uuid);
-
- /**
- * Given a UUID, get the priority order of the corresponding entry in the routing table.
- *
- * @param uuid The UUID to search for.
- * @return The priority order of the corresponding entry, or -1 if there's none.
- */
- public int getRoutingPriorityOrder(UUID uuid);
-
- /**
- * Get all the entries in the routing table, in priority order.
- *
- * @return An immutable list of the routing-table entries.
- */
- public List<FlexAuthzRoutingTableEntry> getAllRoutingTable();
-
- /**
- * @return The number of entries in the routing table.
- */
- public int getRoutingTableSize();
-
- /**
- * Add a new rule to the rule table.
- *
- * @param entry The rule to be added.
- * @throws IllegalArgumentException if there's already a rule of that name in the table.
- */
- public void addToRulesTable(FlexAuthzRule entry);
-
- /**
- * Delete a rule from the rule table.
- *
- * @param displayName The name of the rule to delete.
- * @throws IllegalStateException if the rule is referred to by a routing-table
- * entry, or if there's no rule of that name in the rule table.
- */
- public void deleteFromRulesTable(String displayName);
-
- /**
- * Update a rule in the rule table. Also updates all the routing-table
- * entries that refer to the rule being replaced.
- *
- * @param entry The replacement rule.
- * @throws IllegalArgumentException if there's no rule of that name in the table.
- */
- public void updateRulesTable(FlexAuthzRule entry);
-
- /**
- * Given a name, get the matching rule from the rule table.
- *
- * @param displayName The name to search for.
- * @return The rule with that name, or null if there's none.
- */
- public FlexAuthzRule getFromRulesTable(String displayName);
-
- /**
- * Get all the rules in the rule table.
- *
- * @return An immutable list of the rules in the table.
- */
- public List<FlexAuthzRule> getAllRulesTable();
-
- /**
- * Clear the tables.
- */
- public void clearTables();
-}
diff --git a/src/com/google/enterprise/secmgr/config/FlexAuthorizerImpl.java b/src/com/google/enterprise/secmgr/config/FlexAuthorizerImpl.java
deleted file mode 100644
index f0414a2..0000000
--- a/src/com/google/enterprise/secmgr/config/FlexAuthorizerImpl.java
+++ /dev/null
@@ -1,296 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.inject.Inject;
-
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-/**
- * A basic implementation of FlexAuthorizer. This provides the primary logic
- * for everything except serialization. The routing table is stored as a list
- * and the priority order is the ordering in the list. Each row has a unique
- * identifier. The rule table is stored as a map and the key is the display
- * name of the row.
- *
- * @author meghna@google.com (Meghna Dhar)
- */
-public final class FlexAuthorizerImpl implements FlexAuthorizer {
-
- private static final String ROOT_URL_PATTERN = "/";
-
- private final Map<String, FlexAuthzRule> ruleTable;
- private final List<FlexAuthzRoutingTableEntry> routingTable;
-
- @Inject
- private FlexAuthorizerImpl() {
- ruleTable = Maps.newHashMap();
- routingTable = Lists.newArrayList();
- }
-
- @VisibleForTesting
- FlexAuthorizerImpl(Map<String, FlexAuthzRule> ruleTable,
- List<FlexAuthzRoutingTableEntry> routingTable) {
- this.ruleTable = ruleTable;
- this.routingTable = routingTable;
- }
-
- @Override
- public void addToRoutingTable(int order, FlexAuthzRoutingTableEntry entry) {
- checkPriorityOrder(order, routingTable.size());
- checkForMatchingRule(entry.getAuthzRule());
- routingTable.add(order, entry);
- }
-
- @Override
- public void addToRoutingTable(FlexAuthzRoutingTableEntry entry) {
- checkForMatchingRule(entry.getAuthzRule());
- routingTable.add(entry);
- }
-
- @Override
- public void addToRulesTable(FlexAuthzRule rule) {
- String name = rule.getRowDisplayName();
- Preconditions.checkArgument(ruleTable.get(name) == null,
- "Rule already exists: %s", name);
- ruleTable.put(name, rule);
- }
-
- @Override
- public void clearTables() {
- routingTable.clear();
- ruleTable.clear();
- }
-
- @Override
- public void deleteFromRoutingTable(UUID uuid) {
- Preconditions.checkNotNull(uuid);
- int index = getRoutingPriorityOrder(uuid);
- Preconditions.checkArgument(index >= 0, "Entry not found in routing table: %s", uuid);
- routingTable.remove(index);
- }
-
- @Override
- public void deleteFromRulesTable(String name) {
- Preconditions.checkNotNull(name);
- FlexAuthzRule rule = ruleTable.get(name);
- Preconditions.checkArgument(rule != null, "Rule isn't in table: %s", name);
- for (FlexAuthzRoutingTableEntry entry : routingTable) {
- Preconditions.checkState(entry.getAuthzRule() != rule,
- "Rule '%s' is referred to by one or more routing-table entries: %s",
- name, entry.getUniqueRowId().toString());
- }
- ruleTable.remove(name);
- }
-
- @Override
- public List<FlexAuthzRoutingTableEntry> getAllRoutingTable() {
- return ImmutableList.copyOf(routingTable);
- }
-
- @Override
- public List<FlexAuthzRule> getAllRulesTable() {
- return ImmutableList.copyOf(ruleTable.values());
- }
-
- @Override
- public int getRoutingTableSize() {
- return routingTable.size();
- }
-
- @Override
- public FlexAuthzRoutingTableEntry getFromRoutingTable(UUID uuid) {
- Preconditions.checkNotNull(uuid);
- for (FlexAuthzRoutingTableEntry entry : routingTable) {
- if (uuid.equals(entry.getUniqueRowId())) {
- return entry;
- }
- }
- return null;
- }
-
- @Override
- public FlexAuthzRule getFromRulesTable(String name) {
- Preconditions.checkNotNull(name);
- return ruleTable.get(name);
- }
-
- @Override
- public void updateRoutingTable(int order, FlexAuthzRoutingTableEntry entry) {
- checkPriorityOrder(order, routingTable.size() - 1);
- checkForMatchingRule(entry.getAuthzRule());
- UUID uuid = entry.getUniqueRowId();
- int oldIndex = getRoutingPriorityOrder(uuid);
- Preconditions.checkArgument(oldIndex >= 0, "Entry not found in routing table: %s", uuid);
- // oldIndex is valid in table prior to change; order is where we want the
- // entry to be after the change. So do the delete first, then the insert.
- routingTable.remove(oldIndex);
- routingTable.add(order, entry);
- }
-
- @Override
- public void updateRulesTable(FlexAuthzRule rule) {
- String name = rule.getRowDisplayName();
- FlexAuthzRule oldRule = ruleTable.get(name);
- Preconditions.checkArgument(oldRule != null, "Rule not in table: %s", name);
- ruleTable.put(name, rule);
- // Now update the routing table, replacing the old rule with the new.
- for (int i = 0; i < routingTable.size(); i += 1) {
- FlexAuthzRoutingTableEntry entry = routingTable.get(i);
- if (entry.getAuthzRule() == oldRule) {
- routingTable.set(i,
- new FlexAuthzRoutingTableEntry(
- entry.getUrlPattern(),
- rule,
- entry.getUniqueRowId()));
- }
- }
- }
-
- public int getRoutingPriorityOrder(UUID uuid) {
- Preconditions.checkNotNull(uuid);
- int index = 0;
- for (FlexAuthzRoutingTableEntry entry : routingTable) {
- if (entry.getUniqueRowId().equals(uuid)) {
- return index;
- }
- index++;
- }
- return -1;
- }
-
- private void checkPriorityOrder(int order, int limit) {
- Preconditions.checkArgument(order >= 0 && order <= limit,
- "Priority order not in valid range: %d", order);
- }
-
- private void checkForMatchingRule(FlexAuthzRule rule) {
- String ruleName = rule.getRowDisplayName();
- Preconditions.checkArgument(ruleTable.get(ruleName) == rule,
- "Rule in table doesn't match: %s", ruleName);
- }
-
- @Override
- public String toString() {
- return ConfigSingleton.getGson().toJson(this);
- }
-
- @Override
- public synchronized boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof FlexAuthorizerImpl)) { return false; }
- FlexAuthorizerImpl other = (FlexAuthorizerImpl) object;
- return Objects.equal(getAllRulesTable(), other.getAllRulesTable())
- && Objects.equal(getAllRoutingTable(), other.getAllRoutingTable());
- }
-
- @Override
- public synchronized int hashCode() {
- return Objects.hashCode(getAllRulesTable(), getAllRoutingTable());
- }
-
- public static FlexAuthorizer makeDefault() {
- return makeDefault(null, false);
- }
-
- public static FlexAuthorizer makeDefault(String authzServiceUrl, boolean samlUseBatchedRequests) {
- FlexAuthorizer flexAuthorizer = new FlexAuthorizerImpl();
- int index = 0;
- makeDefaultRule(flexAuthorizer, index++, ROOT_URL_PATTERN,
- AuthzMechanism.CACHE,
- FlexAuthzRule.EMPTY_AUTHN_ID);
- makeDefaultRule(flexAuthorizer, index++, ROOT_URL_PATTERN,
- AuthzMechanism.POLICY,
- FlexAuthzRule.LEGACY_AUTHN_ID);
- if (!Strings.isNullOrEmpty(authzServiceUrl)) {
- makeDefaultRule(flexAuthorizer, index++, ROOT_URL_PATTERN,
- AuthzMechanism.SAML,
- FlexAuthzRule.LEGACY_AUTHN_ID,
- ImmutableMap.of(
- FlexAuthzRule.ParamName.SAML_ENTITY_ID, FlexAuthzRule.LEGACY_SAML_ENTITY_ID,
- FlexAuthzRule.ParamName.SAML_USE_BATCHED_REQUESTS,
- Boolean.toString(samlUseBatchedRequests)));
- }
- makeDefaultRule(flexAuthorizer, index++, FlexAuthzRule.LEGACY_CONNECTOR_URL_PATTERN,
- AuthzMechanism.CONNECTOR,
- FlexAuthzRule.LEGACY_AUTHN_ID,
- ImmutableMap.of(
- FlexAuthzRule.ParamName.CONNECTOR_NAME, FlexAuthzRule.EMPTY_CONNECTOR_NAME));
- makeDefaultRule(flexAuthorizer, index++, ROOT_URL_PATTERN,
- AuthzMechanism.HEADREQUEST,
- FlexAuthzRule.LEGACY_AUTHN_ID);
- return flexAuthorizer;
- }
-
- private static void makeDefaultRule(FlexAuthorizer flexAuthorizer, int index, String urlPattern,
- AuthzMechanism authzMechType, String authnId,
- Map<FlexAuthzRule.ParamName, String> mechSpecificParams) {
- FlexAuthzRule rule
- = new FlexAuthzRule(authnId, authzMechType, mechSpecificParams, String.valueOf(index),
- FlexAuthzRule.NO_TIME_LIMIT);
- flexAuthorizer.addToRulesTable(rule);
- flexAuthorizer.addToRoutingTable(new FlexAuthzRoutingTableEntry(urlPattern, rule));
- }
-
- private static void makeDefaultRule(FlexAuthorizer flexAuthorizer, int index, String urlPattern,
- AuthzMechanism authzMechType, String authnId) {
- FlexAuthzRule rule
- = new FlexAuthzRule(authnId, authzMechType, String.valueOf(index),
- FlexAuthzRule.NO_TIME_LIMIT);
- flexAuthorizer.addToRulesTable(rule);
- flexAuthorizer.addToRoutingTable(new FlexAuthzRoutingTableEntry(urlPattern, rule));
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(FlexAuthorizer.class,
- ProxyTypeAdapter.make(FlexAuthorizer.class, LocalProxy.class));
- }
-
- private static final class LocalProxy implements TypeProxy<FlexAuthorizer> {
- List<FlexAuthzRoutingTableEntry> entries;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(FlexAuthorizer flexAuthorizer) {
- entries = flexAuthorizer.getAllRoutingTable();
- }
-
- @Override
- public FlexAuthorizer build() {
- Map<String, FlexAuthzRule> ruleTable = Maps.newHashMap();
- for (FlexAuthzRoutingTableEntry entry : entries) {
- FlexAuthzRule rule = entry.getAuthzRule();
- ruleTable.put(rule.getRowDisplayName(), rule);
- }
- return new FlexAuthorizerImpl(ruleTable, entries);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/FlexAuthzRoutingTableEntry.java b/src/com/google/enterprise/secmgr/config/FlexAuthzRoutingTableEntry.java
deleted file mode 100644
index d41700d..0000000
--- a/src/com/google/enterprise/secmgr/config/FlexAuthzRoutingTableEntry.java
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.labs.matcher.ParsedUrlPattern;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-
-import java.util.UUID;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-/**
- * Implementation of the Flexible Authorization Routing Table Row.
- *
- * Each row in the routing table contains
- * Url Pattern - a string which specifies either a single document via a
- * specific URL or a set of documents that share the same pattern,
- * pointer to the Authz Rule and a unique row identifier.
- *
- * @author meghna@google.com (Meghna Dhar)
- *
- */
-public class FlexAuthzRoutingTableEntry {
- private final String urlPattern;
- private final FlexAuthzRule authzRule;
- private final UUID uniqueRowId;
-
- public static boolean isValidPattern(String patternStr) {
- if (patternStr.isEmpty()) {
- return false;
- }
- try {
- ParsedUrlPattern p = new ParsedUrlPattern(patternStr);
- } catch (IllegalArgumentException e) {
- return false;
- }
-
- String regexpProtocols[] = new String[] { "regexp:", "regexpIgnoreCase:", "regexpCase:" };
- for (String regexpProtocol : regexpProtocols) {
- if (patternStr.startsWith(regexpProtocol)) {
- try {
- Pattern.compile(patternStr.substring(regexpProtocol.length()));
- } catch (PatternSyntaxException e) {
- return false;
- }
- }
- }
-
- // TODO(???): Introduce addtional validation as ParsedUrlPattern is lax.
- /* GSA rules on valid URL patterns:
- http://code.google.com/apis/searchappliance/documentation/50/help_gsa/z01apprules.html */
-
- return true;
- }
-
- public FlexAuthzRoutingTableEntry(String urlPattern, FlexAuthzRule authzRule) {
- this(urlPattern, authzRule, UUID.randomUUID());
- }
-
- public FlexAuthzRoutingTableEntry(String urlPattern, FlexAuthzRule authzRule,
- UUID uuid) {
- if (!isValidPattern(urlPattern)) {
- throw new IllegalArgumentException("invalid pattern: " + urlPattern);
- }
- this.urlPattern = urlPattern;
- this.authzRule = authzRule;
- this.uniqueRowId = uuid;
- }
-
- public String getUrlPattern() {
- return urlPattern;
- }
-
- public FlexAuthzRule getAuthzRule() {
- return authzRule;
- }
-
- public UUID getUniqueRowId(){
- return uniqueRowId;
- }
-
- @Override
- public String toString() {
- return ConfigSingleton.getGson().toJson(this);
- }
-
- /**
- * only intended to be used for testing
- * Since each time the default config is loaded, there will be a new
- * uniqueRowId generated, we do not include the uniqueRowId in the
- * equals method
- */
- @Override
- public synchronized boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof FlexAuthzRoutingTableEntry)) { return false; }
- FlexAuthzRoutingTableEntry other = (FlexAuthzRoutingTableEntry) object;
- return Objects.equal(getUrlPattern(), other.getUrlPattern())
- && Objects.equal(getAuthzRule(), other.getAuthzRule());
- }
-
- @Override
- public synchronized int hashCode() {
- return Objects.hashCode(getUrlPattern(), getAuthzRule(), getUniqueRowId());
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(FlexAuthzRoutingTableEntry.class,
- ProxyTypeAdapter.make(FlexAuthzRoutingTableEntry.class, LocalProxy.class));
- }
-
- private static final class LocalProxy implements TypeProxy<FlexAuthzRoutingTableEntry> {
- String urlPattern;
- FlexAuthzRule authzRule;
- UUID uniqueRowId;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(FlexAuthzRoutingTableEntry entry) {
- urlPattern = entry.getUrlPattern();
- authzRule = entry.getAuthzRule();
- uniqueRowId = entry.getUniqueRowId();
- }
-
- @Override
- public FlexAuthzRoutingTableEntry build() {
- return new FlexAuthzRoutingTableEntry(urlPattern, authzRule, uniqueRowId);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/FlexAuthzRule.java b/src/com/google/enterprise/secmgr/config/FlexAuthzRule.java
deleted file mode 100644
index c3ae80d..0000000
--- a/src/com/google/enterprise/secmgr/config/FlexAuthzRule.java
+++ /dev/null
@@ -1,283 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * Implementation of the Flexible Authorization Rule.
- *
- * @author meghna@google.com (Meghna Dhar)
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public class FlexAuthzRule {
-
- /**
- * Mechanism-specific parameter names.
- */
- public static enum ParamName {
- /**
- * Indicates a connector-instance name. This is a required string-valued
- * parameter.
- */
- CONNECTOR_NAME,
- /**
- * Indicates the entity ID of a SAML PDP. This is a required string-valued
- * parameter.
- */
- SAML_ENTITY_ID,
- /**
- * Indicates whether to use the "multi-request" authz protocol. This is a
- * required boolean-valued parameter.
- */
- SAML_USE_BATCHED_REQUESTS,
- }
-
- /**
- * The empty authentication ID, for use with mechanisms like
- * {@link AuthzMechanism#CACHE} and {@link AuthzMechanism#POLICY}.
- */
- public static final String EMPTY_AUTHN_ID = "";
-
- /**
- * The legacy authentication ID, for configuration migration.
- */
- public static final String LEGACY_AUTHN_ID = "Default";
-
- /**
- * The empty connector name, for use with {@link #LEGACY_CONNECTOR_URL_PATTERN}.
- */
- public static final String EMPTY_CONNECTOR_NAME = "";
-
- /**
- * The legacy connector URL pattern {@code "^googleconnector://"}.
- */
- public static final String LEGACY_CONNECTOR_URL_PATTERN = "^googleconnector://";
-
- /**
- * The SAML entity ID to use for legacy SAML clients.
- */
- public static final String LEGACY_SAML_ENTITY_ID = "http://example.com/legacy-saml-id";
-
- /**
- * Timeout value that indicates this rule has no specific time limit.
- */
- public static final int NO_TIME_LIMIT = -1;
-
- private static final ImmutableList<AuthzMechanism> AUTHZ_MECHANISMS =
- ImmutableList.copyOf(EnumSet.allOf(AuthzMechanism.class));
-
- @Nonnull private final String authnId;
- @Nonnull private final AuthzMechanism authzMechType;
- @Nonnull private final ImmutableMap<ParamName, String> mechSpecificParams;
- @Nonnull private final String displayName;
- private final int timeout;
-
- /**
- * Constructor for flex authz rules.
- *
- * @param authnId The name of a credential group to use for authorization, or
- * an empty string to use the "primary verified identity".
- * @param authzMechType The authorization mechanism type, for example policy
- * ACLs, head requests, connector authorization, SAML, etc.
- * @param mechSpecificParams A map of parameters that are specific to the
- * mechanism type. A null value is equivalent to an empty map.
- * @param displayName The display name for this rule's row, which can be used
- * as a reference in the routing table.
- * @param timeout The timeout for this rule, in milliseconds.
- */
- public FlexAuthzRule(String authnId, AuthzMechanism authzMechType,
- Map<ParamName, String> mechSpecificParams, String displayName, int timeout) {
- Preconditions.checkNotNull(authnId);
- Preconditions.checkNotNull(authzMechType);
- Preconditions.checkNotNull(displayName);
- this.authnId = authnId;
- this.authzMechType = authzMechType;
- if (mechSpecificParams != null) {
- this.mechSpecificParams = ImmutableMap.copyOf(mechSpecificParams);
- } else {
- this.mechSpecificParams = ImmutableMap.of();
- }
- this.displayName = displayName;
- this.timeout = timeout;
- }
-
- /**
- * A constructor for flex authz rules with no mechanism-specific parameters.
- */
- public FlexAuthzRule(String authnId, AuthzMechanism mechType, String displayName, int timeout) {
- this(authnId, mechType, null, displayName, timeout);
- }
-
- /** A dummy rule to use when only the timeout matters. */
- public static final FlexAuthzRule UNCONSTRAINED
- = new FlexAuthzRule(EMPTY_AUTHN_ID, AuthzMechanism.DENY, "", NO_TIME_LIMIT);
-
- /** A dummy rule to use for fast authorization. */
- public static final FlexAuthzRule FAST_AUTHORIZATION
- = new FlexAuthzRule(EMPTY_AUTHN_ID, AuthzMechanism.DENY, "Fast Authorization", NO_TIME_LIMIT);
-
- /**
- * @return The authentication identity name for this rule: a credential-group
- * name, or the empty string to use the "primary verified identity".
- */
- @Nonnull
- public String getAuthnId() {
- return authnId;
- }
-
- /**
- * @return The authorization mechanism type for this rule.
- */
- @Nonnull
- public AuthzMechanism getAuthzMechType() {
- return authzMechType;
- }
-
- /**
- * @return A collection of the available mechanism types.
- */
- @Nonnull
- public static Collection<AuthzMechanism> getAuthzMechTypes() {
- return AUTHZ_MECHANISMS;
- }
-
- /**
- * @return An immutable copy of the mechanism-specific parameters.
- */
- @Nonnull
- public Map<ParamName, String> getMechSpecificParams() {
- return mechSpecificParams;
- }
-
- @Nonnull
- public String requiredStringParam(ParamName name) {
- String value = mechSpecificParams.get(name);
- Preconditions.checkArgument(value != null);
- return value;
- }
-
- @Nonnull
- public boolean requiredBooleanParam(ParamName name) {
- return Boolean.valueOf(requiredStringParam(name));
- }
-
- /**
- * @return The display name for this rule's row.
- */
- @Nonnull
- public String getRowDisplayName() {
- return displayName;
- }
-
- /**
- * @return The timeout for this rule, in milliseconds.
- */
- public int getTimeout() {
- return timeout;
- }
-
- public boolean hasTimeout() {
- return NO_TIME_LIMIT != timeout;
- }
-
- @Override
- public String toString() {
- return ConfigSingleton.getGson().toJson(this);
- }
-
- @Override
- public synchronized boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof FlexAuthzRule)) { return false; }
- FlexAuthzRule other = (FlexAuthzRule) object;
- return Objects.equal(getAuthnId(), other.getAuthnId())
- && Objects.equal(getAuthzMechType(), other.getAuthzMechType())
- && Objects.equal(getMechSpecificParams(), other.getMechSpecificParams())
- && Objects.equal(getRowDisplayName(), other.getRowDisplayName())
- && Objects.equal(getTimeout(), other.getTimeout());
- }
-
- @Override
- public synchronized int hashCode() {
- return Objects.hashCode(getAuthnId(), getAuthzMechType(), getMechSpecificParams(),
- getRowDisplayName(), getTimeout());
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(FlexAuthzRule.class,
- ProxyTypeAdapter.make(FlexAuthzRule.class, LocalProxy.class));
- }
-
- private static final class LocalProxy implements TypeProxy<FlexAuthzRule> {
- String authnId;
- AuthzMechanism authzMechType;
- String connectorName;
- String samlEntityId;
- String samlUseBatchedRequests;
- String displayName;
- int timeout;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(FlexAuthzRule rule) {
- authnId = rule.getAuthnId();
- authzMechType = rule.getAuthzMechType();
- connectorName = rule.getMechSpecificParams().get(ParamName.CONNECTOR_NAME);
- samlEntityId = rule.getMechSpecificParams().get(ParamName.SAML_ENTITY_ID);
- samlUseBatchedRequests
- = rule.getMechSpecificParams().get(ParamName.SAML_USE_BATCHED_REQUESTS);
- displayName = rule.getRowDisplayName();
- timeout = rule.getTimeout();
- }
-
- @Override
- public FlexAuthzRule build() {
- Map<ParamName, String> mechSpecificParams = Maps.newHashMap();
- if (connectorName != null) {
- mechSpecificParams.put(ParamName.CONNECTOR_NAME, connectorName);
- }
- if (samlEntityId != null) {
- mechSpecificParams.put(ParamName.SAML_ENTITY_ID, samlEntityId);
- }
- if (samlUseBatchedRequests != null) {
- mechSpecificParams.put(ParamName.SAML_USE_BATCHED_REQUESTS, samlUseBatchedRequests);
- }
- if (mechSpecificParams.isEmpty()) {
- mechSpecificParams = null;
- }
- return new FlexAuthzRule(authnId, authzMechType, mechSpecificParams, displayName, timeout);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/ParamName.java b/src/com/google/enterprise/secmgr/config/ParamName.java
deleted file mode 100644
index c131388..0000000
--- a/src/com/google/enterprise/secmgr/config/ParamName.java
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-import java.util.Iterator;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * Configuration parameter names, along with their types and default values.
- */
-@Immutable
-public enum ParamName {
- ACL_GROUPS_FILENAME(String.class, "../../../../conf/acls/acl_groups.enterprise"),
- ACL_URLS_FILENAME(String.class, "../../../../conf/acls/acl_urls.enterprise"),
- CERTIFICATE_AUTHORITIES_FILENAME(String.class, "../../../../conf/certs/cacerts.jks"),
- // whether to check the server certificate during serving time
- CHECK_SERVER_CERTIFICATE(Boolean.class, Boolean.valueOf(true)),
- CONNECTOR_MANAGER_INFO(ConnMgrInfo.class,
- ConnMgrInfo.make(ImmutableSet.<ConnMgrInfo.Entry>of())),
- DENY_RULES_FILENAME(String.class, "../../../../conf/deny_rules.enterprise"),
- GLOBAL_BATCH_REQUEST_TIMEOUT(Float.class, Float.valueOf(2.5f)),
- GLOBAL_SINGLE_REQUEST_TIMEOUT(Float.class, Float.valueOf(5.0f)),
- LATE_BINDING_ACL(Boolean.class, Boolean.valueOf(false)),
- SAML_METADATA_FILENAME(String.class, "../../../../conf/saml-metadata.xml"),
- SERVER_CERTIFICATE_FILENAME(String.class, "../../../../conf/certs/server.jks"),
- SIGNING_CERTIFICATE_FILENAME(String.class, "/etc/google/certs/server.crt"),
- SIGNING_KEY_FILENAME(String.class, "/etc/google/certs/server.key"),
- SLOW_HOST_EMBARGO_PERIOD(Integer.class, Integer.valueOf(600)),
- SLOW_HOST_NUMBER_OF_TIMEOUTS(Integer.class, Integer.valueOf(100)),
- SLOW_HOST_SAMPLE_PERIOD(Integer.class, Integer.valueOf(300)),
- SLOW_HOST_TRACKER_ENABLED(Boolean.class, Boolean.valueOf(false)),
- SLOW_HOST_TRACKER_SIZE(Integer.class, Integer.valueOf(100)),
- STUNNEL_PORT(Integer.class, Integer.valueOf(7843)),
-
- // deprecated params, for backward compatability when reading config
- AUTHZ_CONFIG_FILENAME(String.class, "../../../../conf/FlexAuthz.xml"),
- CONNECTOR_MANAGER_URLS(StringSet.class, new StringSet(ImmutableSet.<String>of()));
-
- private final Class<?> valueClass;
- private final Object defaultValue;
-
- private ParamName(Class<?> valueClass, Object defaultValue) {
- Preconditions.checkNotNull(valueClass);
- Preconditions.checkArgument(valueClass.isInstance(defaultValue));
- this.valueClass = valueClass;
- this.defaultValue = defaultValue;
- }
-
- /**
- * @return The value class for this parameter.
- */
- public Class<?> getValueClass() {
- return valueClass;
- }
-
- /**
- * @return The default value for this parameter.
- */
- public Object getDefaultValue() {
- return defaultValue;
- }
-
- /**
- * Is a given object a valid value for this key?
- *
- * @param value The object to check.
- * @return True only if it would be a valid value.
- */
- public boolean isValidValue(Object value) {
- return valueClass.isInstance(value);
- }
-
- /**
- * Given a string representing a value for this key, converts it to an
- * object.
- *
- * @param value The string to convert.
- * @param valueClass The class of object to convert it to.
- * @return The converted value.
- * @throws IllegalArgumentException if the string can't be converted, or if
- * the value class is inappropriate for this parameter.
- */
- public <T> T stringToValue(String value, Class<T> valueClass) {
- Preconditions.checkNotNull(value);
- Preconditions.checkArgument(valueClass.isAssignableFrom(this.valueClass));
- if (this.valueClass == String.class) {
- return valueClass.cast(value);
- }
- try {
- if (this.valueClass == Integer.class) {
- return valueClass.cast(Integer.valueOf(value));
- }
- if (this.valueClass == Float.class) {
- return valueClass.cast(Float.valueOf(value));
- }
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException(e);
- }
- if (this.valueClass == ConnMgrInfo.class) {
- return valueClass.cast(ConnMgrInfo.valueOf(value));
- }
- if (this.valueClass == StringSet.class) {
- return valueClass.cast(StringSet.valueOf(value));
- }
- throw new IllegalStateException("Unknown value class: " + valueClass.getName());
- }
-
- private static final class StringSet implements Iterable<String> {
-
- final ImmutableSet<String> contents;
-
- StringSet(ImmutableSet<String> contents) {
- this.contents = ImmutableSet.copyOf(contents);
- }
-
- @Override
- public Iterator<String> iterator() {
- return contents.iterator();
- }
-
- /**
- * Decodes a string-encoded string set.
- *
- * @param string The encoded string set.
- * @return The decoded string set.
- */
- public static StringSet valueOf(String string) {
- return ConfigSingleton.getGson().fromJson(string, StringSet.class);
- }
-
- @Override
- public boolean equals(Object object) {
- if (this == object) { return true; }
- if (!(object instanceof StringSet)) { return false; }
- StringSet other = (StringSet) object;
- return Objects.equal(contents, other.contents);
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(contents);
- }
-
- @Override
- public String toString() {
- return ConfigSingleton.getGson().toJson(this);
- }
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(new TypeToken<ImmutableSet<String>>() {}.getType(),
- TypeAdapters.immutableSet());
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/SecurityManagerConfig.java b/src/com/google/enterprise/secmgr/config/SecurityManagerConfig.java
deleted file mode 100644
index e070283..0000000
--- a/src/com/google/enterprise/secmgr/config/SecurityManagerConfig.java
+++ /dev/null
@@ -1,454 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Objects;
-import com.google.common.base.Pair;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.gson.annotations.SerializedName;
-import com.google.gson.reflect.TypeToken;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Locale;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * A class that holds a complete security manager configuration.
- */
-@ThreadSafe
-public final class SecurityManagerConfig {
-
- static final int CURRENT_VERSION = 5;
-
- private final int version;
- @GuardedBy("this") private ImmutableList<CredentialGroup> credentialGroups;
- @GuardedBy("this") private ImmutableList<AuthnMechanism> mechanisms;
- @GuardedBy("this") private ConfigParams params;
- @GuardedBy("this") private FlexAuthorizer flexAuthorizer;
-
- private SecurityManagerConfig(int version, ImmutableList<CredentialGroup> credentialGroups,
- ConfigParams params, FlexAuthorizer flexAuthorizer) {
- this.version = version;
- setCredentialGroupsInternal(credentialGroups);
- this.params = params;
- this.flexAuthorizer = flexAuthorizer;
- }
-
- /**
- * Set a configuration's credential groups. The security manager uses this
- * only for testing.
- *
- * @param credentialGroups The new credential groups.
- * @throws IllegalArgumentException if there's a problem with the argument.
- */
- public void setCredentialGroupsInternal(ImmutableList<CredentialGroup> credentialGroups) {
- ImmutableList.Builder<AuthnMechanism> mechanismsBuilder = ImmutableList.builder();
- for (CredentialGroup credentialGroup : credentialGroups) {
- mechanismsBuilder.addAll(credentialGroup.getMechanisms());
- }
- ImmutableList<AuthnMechanism> mechanisms = mechanismsBuilder.build();
- synchronized (this) {
- this.credentialGroups = credentialGroups;
- this.mechanisms = mechanisms;
- }
- }
-
- /**
- * Make a security manager configuration.
- *
- * @param credentialGroups The configuration's credential groups.
- * @param params The configuration's parameters.
- * @param flexAuthorizer The flex authorization configs
- * @return A security manager configuration.
- */
- public static SecurityManagerConfig make(Iterable<CredentialGroup> credentialGroups,
- ConfigParams params, FlexAuthorizer flexAuthorizer) {
- Preconditions.checkArgument(params != null);
- Preconditions.checkArgument(flexAuthorizer != null);
- return new SecurityManagerConfig(CURRENT_VERSION, checkCredentialGroups(credentialGroups),
- params, flexAuthorizer);
- }
-
- @VisibleForTesting
- public static SecurityManagerConfig make(Iterable<CredentialGroup> credentialGroups) {
- return new SecurityManagerConfig(CURRENT_VERSION, checkCredentialGroups(credentialGroups),
- ConfigParams.makeDefault(),
- FlexAuthorizerImpl.makeDefault());
- }
-
- static SecurityManagerConfig makeInternal(int version, Iterable<CredentialGroup> credentialGroups,
- ConfigParams params, FlexAuthorizer flexAuthorizer) {
- Preconditions.checkArgument(version > 0 && version <= CURRENT_VERSION);
- return new SecurityManagerConfig(
- version,
- checkCredentialGroups(credentialGroups),
- (params != null) ? params : ConfigParams.makeDefault(),
- (flexAuthorizer != null) ? flexAuthorizer : FlexAuthorizerImpl.makeDefault());
- }
-
- private static ImmutableList<CredentialGroup> checkCredentialGroups(
- Iterable<CredentialGroup> credentialGroups) {
- Preconditions.checkNotNull(credentialGroups);
- ImmutableList<CredentialGroup> copy = ImmutableList.copyOf(credentialGroups);
- Collection<String> names = Lists.newArrayList();
- for (CredentialGroup group : copy) {
- checkConfigName(group.getName(), names);
- for (AuthnMechanism mech : group.getMechanisms()) {
- checkConfigName(mech.getName(), names);
- }
- }
- return copy;
- }
-
- private static void checkConfigName(String name, Collection<String> names) {
- if (name != null) {
- name = name.toLowerCase(Locale.US);
- Preconditions.checkArgument(!names.contains(name),
- "Configuration name appears more than once: %s", name);
- names.add(name);
- }
- }
-
- /**
- * @return A default security manager configuration.
- */
- public static SecurityManagerConfig makeDefault() {
- return SecurityManagerConfig.make(
- makeDefaultCredentialGroups(),
- ConfigParams.makeDefault(),
- FlexAuthorizerImpl.makeDefault());
- }
-
- public static ImmutableList<CredentialGroup> makeDefaultCredentialGroups() {
- return ImmutableList.of(CredentialGroup.builder().build());
- }
-
- /**
- * @return The configuration's version.
- */
- int getVersion() {
- return version;
- }
-
- /**
- * Gets the credential groups contained in this configuration.
- *
- * @return The credential groups as an immutable list. The order is the same
- * as was given when this configuration was created.
- */
- public synchronized ImmutableList<CredentialGroup> getCredentialGroups() {
- return credentialGroups;
- }
-
- /**
- * Set a configuration's credential groups. The security manager uses this
- * only for testing.
- *
- * @param credentialGroups The new credential groups.
- * @throws IllegalArgumentException if there's a problem with the argument.
- */
- public void setCredentialGroups(Iterable<CredentialGroup> credentialGroups) {
- setCredentialGroupsInternal(checkCredentialGroups(credentialGroups));
- ConfigSingleton.setChanged();
- }
-
- /**
- * Gets the authentication mechanisms contained in this configuration.
- *
- * @return The mechanisms as an immutable list. The order is the same as was
- * given when this configuration was created.
- */
- public synchronized ImmutableList<AuthnMechanism> getMechanisms() {
- return mechanisms;
- }
-
- /**
- * Gets the credential group for a given mechanism.
- *
- * @param mechanism The mechanism to get the credential group for.
- * @return The credential group for the given mechanism.
- * @throws IllegalArgumentException if the mechanism isn't contained in this
- * configuration.
- */
- public CredentialGroup getCredentialGroup(AuthnMechanism mechanism) {
- for (CredentialGroup credentialGroup : getCredentialGroups()) {
- if (credentialGroup.getMechanisms().contains(mechanism)) {
- return credentialGroup;
- }
- }
- throw new IllegalArgumentException("Unknown mechanism: " + mechanism);
- }
-
- /**
- * Gets the credential group with a given name.
- *
- * @param name The credential-group name to search for.
- * @return The credential group with that name.
- * @throws IllegalArgumentException if there's no credential group with that name.
- */
- public CredentialGroup getCredentialGroup(String name) {
- Preconditions.checkNotNull(name);
- for (CredentialGroup credentialGroup : getCredentialGroups()) {
- if (name.equalsIgnoreCase(credentialGroup.getName())) {
- return credentialGroup;
- }
- }
- throw new IllegalArgumentException("No credential group with this name: " + name);
- }
-
- /**
- * Gets an authority predicate for a given credential group.
- *
- * @param credentialGroup A credential group to get the predicate for.
- * @return The authority predicate for the credential group.
- * @throws IllegalArgumentException if the credential group isn't contained in
- * this configuration.
- */
- public Predicate<AuthnAuthority> getAuthorityPredicate(CredentialGroup credentialGroup) {
- ImmutableSet.Builder<AuthnAuthority> builder = ImmutableSet.builder();
- builder.add(credentialGroup.getAuthority());
- for (AuthnMechanism mechanism : credentialGroup.getMechanisms()) {
- builder.add(mechanism.getAuthority());
- }
- return Predicates.in(builder.build());
- }
-
- public synchronized FlexAuthorizer getFlexAuthorizer() {
- return flexAuthorizer;
- }
-
- /**
- * Sets this configurations's flex authorizer. The security manager uses this
- * only for testing.
- */
- public void setFlexAuthorizer(FlexAuthorizer flexAuthorizer) {
- synchronized (this) {
- this.flexAuthorizer = flexAuthorizer;
- }
- ConfigSingleton.setChanged();
- }
-
- /**
- * @return The configuration parameters.
- */
- public synchronized ConfigParams getParams() {
- return params;
- }
-
- /**
- * Gets a list of credential group name and mechanism name pair for the mechanism.
- *
- * @param mechanismType the authentication mechanism type
- * @return a list of credential group name and mechanism name pair for the mechanism.
- */
- public <T extends AuthnMechanism> List<Pair<String, String>> getMechanism(
- final Class<T> mechanismType) {
- List<Pair<String, String>> mechanisms = Lists.newArrayList();
- for (CredentialGroup group : getCredentialGroups()) {
- for (AuthnMechanism mech : group.getMechanisms()) {
- if (mechanismType.isInstance(mech)) {
- mechanisms.add(Pair.of(group.getName(), mech.getName()));
- }
- }
- }
- return mechanisms;
- }
-
- /**
- * Checks if the mechanism is configured.
- *
- * @param mechanismType the authentication mechanism type
- * @return true if the mechanism is already configured.
- */
- public <T extends AuthnMechanism> boolean hasMechanism(final Class<T> mechanismType) {
- return !getMechanism(mechanismType).isEmpty();
- }
-
- /**
- * Sets a configuration's parameters. The security manager uses this only for
- * testing.
- *
- * @param params The new parameters.
- */
- public void setParams(ConfigParams params) {
- Preconditions.checkNotNull(params);
- synchronized (this) {
- this.params = params;
- }
- ConfigSingleton.setChanged();
- }
-
- /**
- * @return The name of the ACL group rules file, never null or empty.
- */
- public String getAclGroupsFilename() {
- return params.get(ParamName.ACL_GROUPS_FILENAME, String.class);
- }
-
- /**
- * @return The name of the ACL URL rules file, never null or empty.
- */
- public String getAclUrlsFilename() {
- return params.get(ParamName.ACL_URLS_FILENAME, String.class);
- }
-
- /**
- * @return The name of the certificate-authority certificates file, never null
- * or empty.
- */
- public String getCertificateAuthoritiesFilename() {
- return params.get(ParamName.CERTIFICATE_AUTHORITIES_FILENAME, String.class);
- }
-
- /**
- * @return The boolean value whether to check the server certificate during
- * serving time
- */
- public Boolean getCheckServerCertificate() {
- return params.get(ParamName.CHECK_SERVER_CERTIFICATE, Boolean.class);
- }
-
- /**
- * @return The URLs of the configured connector managers as an immutable set.
- */
- public StringSet getConnectorManagerUrls() {
- return params.get(ParamName.CONNECTOR_MANAGER_URLS, StringSet.class);
- }
-
- /**
- * @return The name of the http deny rules file, never null or empty.
- */
- public String getDenyRulesFilename() {
- return params.get(ParamName.DENY_RULES_FILENAME, String.class);
- }
-
- /**
- * @return The global batch request timeout.
- */
- public Float getGlobalBatchRequestTimeout() {
- return params.get(ParamName.GLOBAL_BATCH_REQUEST_TIMEOUT, Float.class);
- }
-
- /**
- * @return The global single request timeout.
- */
- public Float getGlobalSingleRequestTimeout() {
- return params.get(ParamName.GLOBAL_SINGLE_REQUEST_TIMEOUT, Float.class);
- }
-
- /**
- * @return The name of the SAML metadata configuration file, never null or
- * empty.
- */
- public String getSamlMetadataFilename() {
- return params.get(ParamName.SAML_METADATA_FILENAME, String.class);
- }
-
- /**
- * @return The name of the security manager's certificate file, never null or
- * empty.
- */
- public String getServerCertificateFilename() {
- return params.get(ParamName.SERVER_CERTIFICATE_FILENAME, String.class);
- }
-
- /**
- * @return The name of the certificate file to be used for signing outgoing
- * messages, never null or empty.
- */
- public String getSigningCertificateFilename() {
- return params.get(ParamName.SIGNING_CERTIFICATE_FILENAME, String.class);
- }
-
- /**
- * @return The name of the key file to be used for signing outgoing messages,
- * never null or empty.
- */
- public String getSigningKeyFilename() {
- return params.get(ParamName.SIGNING_KEY_FILENAME, String.class);
- }
-
- /**
- * @return The port of the stunnel service that is forwarding to the security manager.
- */
- public int getStunnelPort() {
- return params.get(ParamName.STUNNEL_PORT, Integer.class);
- }
-
- @Override
- public String toString() {
- return ConfigSingleton.getGson().toJson(this);
- }
-
- @Override
- public synchronized boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof SecurityManagerConfig)) { return false; }
- SecurityManagerConfig other = (SecurityManagerConfig) object;
- return Objects.equal(getVersion(), other.getVersion())
- && Objects.equal(getCredentialGroups(), other.getCredentialGroups())
- && Objects.equal(getParams(), other.getParams())
- && Objects.equal(getFlexAuthorizer(), other.getFlexAuthorizer());
- }
-
- @Override
- public synchronized int hashCode() {
- return Objects.hashCode(getVersion(), getCredentialGroups(), getParams(), getFlexAuthorizer());
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(SecurityManagerConfig.class,
- ProxyTypeAdapter.make(SecurityManagerConfig.class, LocalProxy.class));
- builder.registerTypeAdapter(new TypeToken<ImmutableList<CredentialGroup>>() {}.getType(),
- TypeAdapters.immutableList());
- }
-
- private static final class LocalProxy implements TypeProxy<SecurityManagerConfig> {
- int version;
- @SerializedName("CGs") ImmutableList<CredentialGroup> credentialGroups;
- ConfigParams params;
- @SerializedName("flexAuthz") FlexAuthorizer flexAuthorizer;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(SecurityManagerConfig config) {
- version = config.getVersion();
- credentialGroups = config.getCredentialGroups();
- params = config.getParams();
- flexAuthorizer = config.getFlexAuthorizer();
- }
-
- @Override
- public SecurityManagerConfig build() {
- return makeInternal(version, credentialGroups, params, flexAuthorizer);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/config/StringSet.java b/src/com/google/enterprise/secmgr/config/StringSet.java
deleted file mode 100644
index db6bdea..0000000
--- a/src/com/google/enterprise/secmgr/config/StringSet.java
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableSet;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-import java.util.Iterator;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * An implementation of Set<String> with a reliable string representation.
- */
-@Immutable
-public final class StringSet implements Iterable<String> {
-
- private final ImmutableSet<String> contents;
-
- private StringSet(ImmutableSet<String> contents) {
- this.contents = contents;
- }
-
- /**
- * Makes a new string set.
- *
- * @param contents The contents of the new set.
- * @return A new set with the given contents.
- */
- public static StringSet make(Iterable<String> contents) {
- return new StringSet(ImmutableSet.copyOf(contents));
- }
-
- /**
- * Makes a new string set.
- *
- * @param contents The contents of the new set.
- * @return A new set with the given contents.
- */
- public static StringSet make(String... contents) {
- return new StringSet(ImmutableSet.copyOf(contents));
- }
-
- @Override
- public Iterator<String> iterator() {
- return contents.iterator();
- }
-
- @Override
- public boolean equals(Object object) {
- if (this == object) { return true; }
- if (!(object instanceof StringSet)) { return false; }
- StringSet other = (StringSet) object;
- return Objects.equal(contents, other.contents);
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(contents);
- }
-
- @Override
- public String toString() {
- return ConfigSingleton.getGson().toJson(this);
- }
-
- /**
- * Decodes a string-encoded string set.
- *
- * @param string The encoded string set.
- * @return The decoded string set.
- */
- public static StringSet valueOf(String string) {
- return ConfigSingleton.getGson().fromJson(string, StringSet.class);
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(StringSet.class,
- ProxyTypeAdapter.make(StringSet.class, LocalProxy.class));
- builder.registerTypeAdapter(new TypeToken<ImmutableSet<String>>() {}.getType(),
- TypeAdapters.immutableSet());
- }
-
- private static final class LocalProxy implements TypeProxy<StringSet> {
- ImmutableSet<String> contents;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(StringSet set) {
- contents = set.contents;
- }
-
- @Override
- public StringSet build() {
- return make(contents);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/http/ConnectorUtil.java b/src/com/google/enterprise/secmgr/http/ConnectorUtil.java
deleted file mode 100644
index 7ced38b..0000000
--- a/src/com/google/enterprise/secmgr/http/ConnectorUtil.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * 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.google.enterprise.secmgr.http;
-
-import static com.google.enterprise.secmgr.common.XmlUtil.findChildElement;
-import static com.google.enterprise.secmgr.common.XmlUtil.getChildElementText;
-import static com.google.enterprise.secmgr.common.XmlUtil.getChildElements;
-import static com.google.enterprise.secmgr.common.XmlUtil.isElementWithQname;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.enterprise.secmgr.common.XmlUtil;
-import com.google.enterprise.secmgr.config.ConfigSingleton;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.ls.LSException;
-import org.w3c.dom.ls.LSSerializer;
-
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.StringWriter;
-import java.net.URL;
-import java.util.Map;
-import java.util.Observable;
-import java.util.Observer;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.xml.namespace.QName;
-
-public final class ConnectorUtil {
-
- // Don't instantiate.
- private ConnectorUtil() {
- throw new UnsupportedOperationException();
- }
-
- private static final Logger LOGGER = Logger.getLogger(ConnectorUtil.class.getName());
-
- private static QName cmname(String localPart) {
- return new QName(localPart);
- }
-
- // All of these QName constants are exposed for testing.
- public static final QName XML_TAG_ANSWER = cmname("Answer");
- public static final QName XML_TAG_AUTHN_CREDENTIAL = cmname("Credentials");
- public static final QName XML_TAG_AUTHN_DOMAIN = cmname("Domain");
- public static final QName XML_TAG_AUTHN_PASSWORD = cmname("Password");
- public static final QName XML_TAG_AUTHN_REQUEST = cmname("AuthnRequest");
- public static final QName XML_TAG_AUTHN_RESPONSE = cmname("AuthnResponse");
- public static final QName XML_TAG_AUTHN_USERNAME = cmname("Username");
- public static final QName XML_TAG_AUTHZ_QUERY = cmname("AuthorizationQuery");
- public static final QName XML_TAG_AUTHZ_RESPONSE = cmname("AuthorizationResponse");
- public static final QName XML_TAG_CONNECTORS = cmname("Connectors");
- public static final QName XML_TAG_CONNECTOR_INSTANCE = cmname("ConnectorInstance");
- public static final QName XML_TAG_CONNECTOR_INSTANCES = cmname("ConnectorInstances");
- public static final QName XML_TAG_CONNECTOR_NAME = cmname("ConnectorName");
- public static final QName XML_TAG_CONNECTOR_QUERY = cmname("ConnectorQuery");
- public static final QName XML_TAG_CONNECTOR_TYPE = cmname("ConnectorType");
- public static final QName XML_TAG_DECISION = cmname("Decision");
- public static final QName XML_TAG_FAILURE = cmname("Failure");
- public static final QName XML_TAG_GROUP = cmname("Group");
- public static final QName XML_TAG_IDENTITY = cmname("Identity");
- public static final QName XML_TAG_INFO = cmname("Info");
- public static final QName XML_TAG_RESOURCE = cmname("Resource");
- public static final QName XML_TAG_RESPONSE_ROOT = cmname("CmResponse");
- public static final QName XML_TAG_STATUS_ID = cmname("StatusId");
- public static final QName XML_TAG_SUCCESS = cmname("Success");
-
- // The connector name attribute should be lower case, however the
- // connector manager used this form so we have to change to the current.
- public static final QName XML_ATTR_CONNECTOR_NAME = cmname("ConnectorName");
-
- public static final QName XML_ATTR_DOMAIN = cmname("domain");
- public static final QName XML_ATTR_PASSWORD = cmname("password");
-
- public static final String CONFIG_XML_DECLARATION = "xml-declaration";
-
- public static final String DECISION_TEXT_PERMIT = "permit";
- public static final String DECISION_TEXT_DENY = "deny";
- public static final String DECISION_TEXT_INDETERMINATE = "indeterminate";
-
- public static final String CM_AUTHENTICATE_SERVLET_PATH = "/authenticate";
- public static final String CM_AUTHORIZATION_SERVLET_PATH = "/authorization";
- public static final String CM_INSTANCE_LIST_SERVLET_PATH = "/getConnectorInstanceList";
-
- public static final String LOG_RESPONSE_EMPTY_NODE = "Empty node";
-
- public static final int SUCCESS = 0;
- public static final int RESPONSE_EMPTY_NODE = 5213;
- public static final int RESPONSE_NULL_CONNECTOR = 5215;
- public static final int ERROR_PARSING_XML_REQUEST = 5300;
-
- @GuardedBy("class") private static Map<String, String> urlMap;
- @GuardedBy("class") private static boolean isInitialized;
-
- public static synchronized void initialize() {
- if (!isInitialized) {
- ConfigSingleton.getObservable().addObserver(LOCAL_OBSERVER);
- isInitialized = true;
- }
- }
-
- @VisibleForTesting
- public static synchronized void initializeForTesting(Map<String, String> urlMap) {
- ConfigSingleton.getObservable().deleteObserver(LOCAL_OBSERVER);
- ConnectorUtil.urlMap = urlMap;
- isInitialized = true;
- }
-
- private static final Observer LOCAL_OBSERVER
- = new Observer() {
- @Override
- public void update(Observable observable, Object object) {
- reinitializeUrlMap();
- }
- };
-
- private static void reinitializeUrlMap() {
- ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
- Iterable<String> urls;
- try {
- urls = ConfigSingleton.getConnectorManagerUrls();
- } catch (IOException e) {
- LOGGER.log(Level.SEVERE, "Unable to get list of connector manager URLs: ", e);
- return;
- }
- for (String url : urls) {
- Set<String> instances;
- try {
- instances = getInstances(url);
- } catch (IOException e) {
- LOGGER.log(Level.WARNING, "Unable to read connector instances from " + url + ": ", e);
- continue;
- }
- for (String instance : instances) {
- builder.put(instance, url);
- }
- }
- synchronized (ConnectorUtil.class) {
- urlMap = builder.build();
- }
- }
-
- /**
- * @return An immutable map from connector-instance name to connector-manager URL.
- */
- public static synchronized Map<String, String> getUrlMap() {
- if (urlMap == null) {
- reinitializeUrlMap();
- }
- return urlMap;
- }
-
- /**
- * Gets the connector-manager URL associated with a given connector-instance name.
- *
- * @param instanceName The connector instance name to look up.
- * @return The corresponding connector-manager URL, or null if none.
- */
- public static String getInstanceManagerUrl(String instanceName) {
- return getUrlMap().get(instanceName);
- }
-
- /**
- * Gets the connector-manager URL associated with a given connector-instance name.
- *
- * @param instanceName The connector instance name to look up.
- * @return The corresponding connector-manager URL.
- * @throws IllegalArgumentException if the URL is unknown.
- */
- public static String requireInstanceManagerUrl(String instanceName) {
- String url = getInstanceManagerUrl(instanceName);
- Preconditions.checkArgument(url != null);
- return url;
- }
-
- /**
- * Get a list of connector instances from a connector manager.
- *
- * @param managerUrl The URL for the connector manager.
- * @return An immutable set of the instance names from the connector manager.
- */
- private static Set<String> getInstances(String managerUrl)
- throws IOException {
- Preconditions.checkNotNull(managerUrl);
- return parseInstanceListResponse(doExchange(null, managerUrl + CM_INSTANCE_LIST_SERVLET_PATH,
- -1));
- }
-
- private static Set<String> parseInstanceListResponse(Document document) {
- Element root = document.getDocumentElement();
- ImmutableSet.Builder<String> builder = ImmutableSet.builder();
- if (!isElementWithQname(root, XML_TAG_RESPONSE_ROOT)) {
- LOGGER.warning("Unexpected response from connector manager:" + root);
- return builder.build();
- }
- Element instances = findChildElement(root, XML_TAG_CONNECTOR_INSTANCES, false);
- if (instances != null) {
- for (Element instance : getChildElements(instances, XML_TAG_CONNECTOR_INSTANCE)) {
- builder.add(getChildElementText(instance, XML_TAG_CONNECTOR_NAME, true));
- }
- }
- return builder.build();
- }
-
- /**
- */
- public static Document doExchange(Document request, String cmUrlString, int timeout)
- throws IOException {
- HttpExchange exchange = sendRequest(request, cmUrlString, timeout);
- Document response;
- try {
- response = XmlUtil.getInstance().readXmlDocument(
- new InputStreamReader(exchange.getResponseEntityAsStream(), "UTF-8"));
- } finally {
- exchange.close();
- }
- return response;
- }
-
- private static HttpExchange sendRequest(Document request, String cmUrlString, int timeout)
- throws IOException {
- HttpClientInterface httpClient = HttpClientUtil.getHttpClient();
- HttpExchange exchange = httpClient.postExchange(new URL(cmUrlString), null);
- if (timeout >= 0) {
- exchange.setTimeout(timeout);
- }
- try {
- exchange.setRequestHeader("Content-Type", "text/xml");
- exchange.setRequestBody(documentToString(request).getBytes("UTF-8"));
- int status = exchange.exchange();
- if (status > 300) {
- throw new IOException("Message exchange returned status: " + status);
- }
- } catch (IOException e) {
- exchange.close();
- throw e;
- }
- return exchange;
- }
-
- private static String documentToString(Document document)
- throws IOException {
- if (document == null) {
- return "";
- }
- XmlUtil xmlUtil = XmlUtil.getInstance();
- LSSerializer serializer = xmlUtil.makeSerializer();
- // Don't generate <?xml ... ?> line.
- serializer.getDomConfig().setParameter(CONFIG_XML_DECLARATION, false);
- StringWriter output = new StringWriter();
- try {
- XmlUtil.writeXmlDocument(document, serializer, xmlUtil.getLsOutput(output));
- } catch (LSException e) {
- throw new IOException(e);
- }
- return output.toString();
- }
-}
diff --git a/src/com/google/enterprise/secmgr/http/HttpClientInterface.java b/src/com/google/enterprise/secmgr/http/HttpClientInterface.java
index b34c8b5..1689938 100644
--- a/src/com/google/enterprise/secmgr/http/HttpClientInterface.java
+++ b/src/com/google/enterprise/secmgr/http/HttpClientInterface.java
@@ -16,7 +16,6 @@
import com.google.common.collect.ListMultimap;
-import java.io.IOException;
import java.net.URL;
import javax.annotation.Nonnull;
@@ -28,22 +27,6 @@
*/
public interface HttpClientInterface {
/**
- * Create a new HTTP HEAD exchange object.
- *
- * @param url The URL to send the request to.
- * @return A new HTTP exchange object.
- */
- public HttpExchange headExchange(@Nonnull URL url);
-
- /**
- * Create a new HTTP GET exchange object.
- *
- * @param url The URL to send the request to.
- * @return A new HTTP exchange object.
- */
- public HttpExchange getExchange(@Nonnull URL url);
-
- /**
* Create a new HTTP POST exchange object.
*
* @param url The URL to send the request to.
@@ -52,79 +35,4 @@
*/
public HttpExchange postExchange(@Nonnull URL url,
@Nullable ListMultimap<String, String> parameters);
-
- /**
- * Create a new HTTP GET or HEAD exchange object.
- * The method (GET or HEAD) is determined by the configuration for the URL.
- *
- * @param url The URL to send the request to.
- * @return A new HTTP exchange object.
- */
- public HttpExchange newHttpExchange(@Nonnull URL url);
-
- /**
- * A marker type for an object representing an HTTP connection.
- */
- public interface Connection {
-
- /**
- * Close the connection. After calling this method, the connection can't
- * be used for further communication.
- */
- public void close() throws IOException;
- }
-
- /**
- * Get a persistent connection for a given URL.
- * The returned connection may be used multiple times.
- * Calling this twice returns two different connections.
- *
- * @param url A URL specifying where to connect to.
- * @return A new connection to the specified host.
- */
- public Connection getConnection(@Nonnull URL url) throws IOException;
-
- /**
- * Create a new HTTP HEAD exchange object.
- *
- * @param connection The connection to send the request over.
- * @param url The URL to send the request to.
- * @return A new HTTP exchange object.
- */
- public HttpExchange headExchange(@Nullable Connection connection, @Nonnull URL url);
-
- /**
- * Create a new HTTP GET exchange object.
- *
- * @param connection The connection to send the request over.
- * @param url The URL to send the request to.
- * @return A new HTTP exchange object.
- */
- public HttpExchange getExchange(@Nullable Connection connection, @Nonnull URL url);
-
- /**
- * Create a new HTTP POST exchange object.
- *
- * @param connection The connection to send the request over.
- * @param url The URL to send the request to.
- * @param parameters The POST parameters.
- * @return A new HTTP exchange object.
- */
- public HttpExchange postExchange(@Nullable Connection connection, @Nonnull URL url,
- @Nullable ListMultimap<String, String> parameters);
-
- /**
- * Create a new HTTP GET or HEAD exchange object.
- * The method (GET or HEAD) is determined by the configuration for the URL.
- *
- * @param connection The connection to send the request over.
- * @param url The URL to send the request to.
- * @return A new HTTP exchange object.
- */
- public HttpExchange newHttpExchange(@Nullable Connection connection, @Nonnull URL url);
-
- /**
- * Sets connection timeout and socket timeout.
- */
- public void setRequestTimeoutMillis(int millisec);
}
diff --git a/src/com/google/enterprise/secmgr/http/HttpClientUtil.java b/src/com/google/enterprise/secmgr/http/HttpClientUtil.java
deleted file mode 100644
index 613edb5..0000000
--- a/src/com/google/enterprise/secmgr/http/HttpClientUtil.java
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.http;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.enterprise.secmgr.common.CookieStore;
-import com.google.enterprise.secmgr.common.GCookie;
-import com.google.enterprise.secmgr.common.HttpUtil;
-import com.google.enterprise.secmgr.config.ConfigSingleton;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * Utilities useful throughout the security manager.
- */
-@ThreadSafe
-public class HttpClientUtil {
-
- // don't instantiate
- private HttpClientUtil() {
- throw new UnsupportedOperationException();
- }
-
- @GuardedBy("class") private static HttpClientInterface clientOverride = null;
-
- /**
- * Get an HTTP client to use when communicating with client servers.
- *
- * @return An HTTP client.
- */
- public static HttpClientInterface getHttpClient() {
- synchronized (HttpClientUtil.class) {
- if (clientOverride != null) {
- return clientOverride;
- }
- }
- return ConfigSingleton.getInstance(HttpClientInterface.class);
- }
-
- /**
- * Set the HTTP client to use when communicating with client servers. To be
- * used by unit tests to override the default transport mechanism.
- *
- * @param client An HTTP client.
- */
- @VisibleForTesting
- public static void setHttpClient(HttpClientInterface client) {
- Preconditions.checkNotNull(client);
- synchronized (HttpClientUtil.class) {
- clientOverride = client;
- }
- }
-
- /**
- * Return the redirect location of an HTTP response.
- *
- * @param exchange The HTTP exchange object containing the response.
- * @return The URL from a <code>Refresh</code> or <code>Location</code>
- * header, or null if none such.
- */
- public static String getRedirectUrl(HttpExchange exchange) {
- int status = exchange.getStatusCode();
- if (HttpUtil.isGoodHttpStatus(status)) {
- return HttpClientUtil.getRefreshUrl(exchange);
- }
- if (status >= 300 && status < 400) {
- return exchange.getResponseHeaderValue("Location");
- }
- return null;
- }
-
- /**
- * Get the relative URL string in Refresh header if exists.
- * @param exchange The HTTP exchange object.
- * @return The relative URL string of Refresh header or null
- * if none exists
- */
- private static String getRefreshUrl(HttpExchange exchange) {
- String refresh = exchange.getResponseHeaderValue("Refresh");
- if (refresh != null) {
- int pos = refresh.indexOf(';');
- if (pos != -1) {
- // found a semicolon
- String timeToRefresh = refresh.substring(0, pos);
- if ("0".equals(timeToRefresh)) {
- // only follow this if its an immediate refresh (0 seconds)
- pos = refresh.indexOf('=');
- if (pos != -1 && (pos + 1) < refresh.length()) {
- return refresh.substring(pos + 1);
- }
- }
- }
- }
- return null;
- }
-
- /**
- * Parses cookies from the headers of an HTTP response.
- *
- * @param exchange The exchange to get the response headers from.
- * @param sessionId A session ID to add to log messages.
- * @param store A cookie store to which the parsed cookies will be added.
- */
- public static void parseHttpResponseCookies(HttpExchange exchange, String sessionId,
- CookieStore store) {
- GCookie.parseResponseHeaders(
- exchange.getResponseHeaderValues(HttpUtil.HTTP_HEADER_SET_COOKIE),
- HttpUtil.toUri(exchange.getUrl()),
- sessionId,
- store);
- }
-}
diff --git a/src/com/google/enterprise/secmgr/http/HttpExchange.java b/src/com/google/enterprise/secmgr/http/HttpExchange.java
index 969ec96..c3b0b29 100644
--- a/src/com/google/enterprise/secmgr/http/HttpExchange.java
+++ b/src/com/google/enterprise/secmgr/http/HttpExchange.java
@@ -15,8 +15,6 @@
package com.google.enterprise.secmgr.http;
import com.google.common.collect.ListMultimap;
-import com.google.enterprise.secmgr.common.CookieStore;
-import com.google.enterprise.secmgr.common.GCookie;
import java.io.IOException;
import java.io.InputStream;
@@ -123,23 +121,6 @@
public String getRequestHeaderValue(String headerName);
/**
- * Adds cookies to this exchange's request.
- *
- * @param cookies The cookies to add.
- */
- public void addCookies(Iterable<GCookie> cookies);
-
- /**
- * Gets this exchange's cookies. Prior to calling {@link #exchange} this will
- * return the request cookies; subsequently it will return cookies as modified
- * by the response.
- *
- * @return The exchange's cookie store.
- */
- @Nonnull
- public CookieStore getCookies();
-
- /**
* Sets the entity of the request.
*
* @param byteArrayRequestEntity The bytes to use as an entity.
diff --git a/src/com/google/enterprise/secmgr/identity/AbstractCredential.java b/src/com/google/enterprise/secmgr/identity/AbstractCredential.java
deleted file mode 100644
index a311a15..0000000
--- a/src/com/google/enterprise/secmgr/identity/AbstractCredential.java
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.identity;
-
-import com.google.common.base.Predicate;
-import com.google.enterprise.secmgr.config.ConfigSingleton;
-
-/**
- * A base class for all credentials.
- *
- * @see Credential
- */
-public abstract class AbstractCredential implements Credential {
-
- /**
- * Get a predicate for a given credential subtype. This predicate is true
- * only of credentials of that type.
- *
- * @param clazz The class of the credential subtype to test for.
- * @return The requested predicate.
- */
- public static final Predicate<Credential> getTypePredicate(
- final Class<? extends Credential> clazz) {
- return new Predicate<Credential>() {
- public boolean apply(Credential credential) {
- return clazz.isInstance(credential);
- }
- };
- }
-
- @Override
- public String toString() {
- return ConfigSingleton.getGson().toJson(this);
- }
-}
diff --git a/src/com/google/enterprise/secmgr/identity/AuthnPrincipal.java b/src/com/google/enterprise/secmgr/identity/AuthnPrincipal.java
deleted file mode 100644
index dbe136a..0000000
--- a/src/com/google/enterprise/secmgr/identity/AuthnPrincipal.java
+++ /dev/null
@@ -1,206 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.identity;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.enterprise.secmgr.common.Stringify;
-import com.google.enterprise.secmgr.config.CredentialTypeName;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A credential that contains the user's name and optionally some domain info.
- *
- * A principal may be stored in an identity's credential set. Doing so doesn't
- * imply that it's verified; that's true only if the identity has a verification
- * that explicitly includes the principal.
- *
- * @see Verification
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class AuthnPrincipal extends AbstractCredential
- implements java.security.Principal {
-
- @Nonnull private final String name;
- @Nullable private final String activeDirectoryDomain;
-
- private AuthnPrincipal(String name, @Nullable String activeDirectoryDomain) {
- super();
- Preconditions.checkNotNull(name);
- this.name = name;
- this.activeDirectoryDomain = activeDirectoryDomain;
- }
-
- /**
- * Makes a principal.
- *
- * @param name The principal's name; may not be null.
- * @param activeDirectoryDomain The ActiveDirectory domain name; may be null.
- * @return A principal with the given components.
- */
- @Nonnull
- public static AuthnPrincipal make(String name, @Nullable String activeDirectoryDomain) {
- return new AuthnPrincipal(name, activeDirectoryDomain);
- }
-
- /**
- * Makes a principal with no domain.
- *
- * @param name The username.
- * @return A principal with the given username and no domain.
- */
- @Nonnull
- public static AuthnPrincipal make(String name) {
- return new AuthnPrincipal(name, null);
- }
-
- /**
- * Gets the name associated with this identity. Usually a "user name" or
- * "login name".
- *
- * @return The identity's name as a string.
- */
- @Nonnull
- public String getName() {
- return name;
- }
-
- /**
- * Gets the Active Directory Domain name associated with this identity.
- *
- * @return The domain name as a string.
- */
- @Nullable
- public String getActiveDirectoryDomain() {
- return activeDirectoryDomain;
- }
-
- @Override
- public boolean isPublic() {
- return true;
- }
-
- @Override
- public CredentialTypeName getTypeName() {
- return CredentialTypeName.PRINCIPAL;
- }
-
- @Override
- public boolean isVerifiable() {
- return !name.isEmpty();
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof AuthnPrincipal)) { return false; }
- AuthnPrincipal principal = (AuthnPrincipal) object;
- return Objects.equal(name, principal.getName())
- && Objects.equal(activeDirectoryDomain, principal.getActiveDirectoryDomain());
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(name, activeDirectoryDomain);
- }
-
- @Override
- public String toString() {
- return "{principal: " + Stringify.object(joinUsernameDomain(name, activeDirectoryDomain)) + "}";
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(AuthnPrincipal.class,
- ProxyTypeAdapter.make(AuthnPrincipal.class, LocalProxy.class));
- }
-
- private static final class LocalProxy implements TypeProxy<AuthnPrincipal> {
- String name;
- String activeDirectoryDomain;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(AuthnPrincipal principal) {
- name = principal.getName();
- activeDirectoryDomain = principal.getActiveDirectoryDomain();
- }
-
- @Override
- public AuthnPrincipal build() {
- return make(name, activeDirectoryDomain);
- }
- }
-
- /**
- * Parses a string into a principal.
- *
- * @param string The combined username/domain string.
- * @return A principal with the separated username and domain.
- * @see #parseUsernameDomain
- */
- @Nonnull
- public static AuthnPrincipal parse(String string) {
- String[] parsed = parseUsernameDomain(string);
- return make(parsed[0], parsed[1]);
- }
-
- /**
- * Parses a string into a username/domain pair.
- *
- * @param string The combined username/domain string.
- * @return The username and domain strings as an array.
- */
- @Nonnull
- public static String[] parseUsernameDomain(String string) {
- Preconditions.checkNotNull(string);
- int slash = string.indexOf("\\");
- if (slash == -1) {
- slash = string.indexOf("/");
- }
- if (slash >= 0) {
- return new String[] { string.substring(slash + 1), string.substring(0, slash) };
- }
- int atSign = string.indexOf("@");
- if (atSign >= 0) {
- return new String[] { string.substring(0, atSign), string.substring(atSign + 1) };
- }
- return new String[] { string, null };
- }
-
- /**
- * Joins a username and domain into a string.
- *
- * @param username The username.
- * @param domain The domain, or {@code null} if none.
- * @return The combined username/domain string.
- */
- @Nonnull
- public static String joinUsernameDomain(String username, @Nullable String domain) {
- Preconditions.checkNotNull(username);
- return (Strings.isNullOrEmpty(domain)) ? username : username + "@" + domain;
- }
-}
diff --git a/src/com/google/enterprise/secmgr/identity/CredPassword.java b/src/com/google/enterprise/secmgr/identity/CredPassword.java
deleted file mode 100644
index ab2de0a..0000000
--- a/src/com/google/enterprise/secmgr/identity/CredPassword.java
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.identity;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.enterprise.secmgr.config.CredentialTypeName;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.gson.annotations.SerializedName;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A credential consisting of a password.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class CredPassword extends AbstractCredential {
-
- @Nonnull private final String text;
-
- private CredPassword(String text) {
- Preconditions.checkNotNull(text);
- this.text = text;
- }
-
- /**
- * Gets a password credential for a given password text.
- *
- * @param text The text of the password.
- * @return A corresponding password credential.
- */
- @Nonnull
- public static CredPassword make(String text) {
- return new CredPassword(text);
- }
-
- @Override
- public boolean isPublic() {
- return false;
- }
-
- @Override
- public CredentialTypeName getTypeName() {
- return CredentialTypeName.PASSWORD;
- }
-
- @Override
- public boolean isVerifiable() {
- return !text.isEmpty();
- }
-
- /**
- * Gets the user's password.
- *
- * @return The password text.
- */
- @Nonnull
- public String getText() {
- return text;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof CredPassword)) { return false; }
- CredPassword credential = (CredPassword) object;
- return Objects.equal(text, credential.getText());
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(text);
- }
-
- @Override
- public String toString() {
- return "{password}";
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(CredPassword.class,
- ProxyTypeAdapter.make(CredPassword.class, LocalProxy.class));
- }
-
- private static final class LocalProxy implements TypeProxy<CredPassword> {
- @SerializedName("password") String text;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(CredPassword password) {
- text = password.getText();
- }
-
- @Override
- public CredPassword build() {
- return make(text);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/identity/Credential.java b/src/com/google/enterprise/secmgr/identity/Credential.java
deleted file mode 100644
index b66dba8..0000000
--- a/src/com/google/enterprise/secmgr/identity/Credential.java
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.identity;
-
-import com.google.enterprise.secmgr.config.CredentialTypeName;
-
-/**
- * A credential. Examples of credentials include: username, password, kerberos
- * ticket, X.509 certificate.
- */
-public interface Credential {
-
- /**
- * Is it OK for this credential to be shared with others?
- *
- * Examples of public credentials include: username, X.509 credential.
- * Examples of private credentials include: password, private key.
- *
- * @return True if the credential is public, false if it's private.
- */
- public boolean isPublic();
-
- /**
- * @return The name of this credential's type.
- */
- public CredentialTypeName getTypeName();
-
- /**
- * @return True if the credential is verifiable.
- */
- public boolean isVerifiable();
-}
diff --git a/src/com/google/enterprise/secmgr/identity/CredentialModule.java b/src/com/google/enterprise/secmgr/identity/CredentialModule.java
deleted file mode 100644
index 08e7100..0000000
--- a/src/com/google/enterprise/secmgr/identity/CredentialModule.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * 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.google.enterprise.secmgr.identity;
-
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.gson.GsonBuilder;
-
-/**
- * A module for top-level configuration of this package.
- */
-public final class CredentialModule {
-
- // Don't instantiate.
- private CredentialModule() {
- throw new UnsupportedOperationException();
- }
-
- public static void registerTypeAdapters(GsonBuilder builder) {
- AuthnPrincipal.registerTypeAdapters(builder);
- CredPassword.registerTypeAdapters(builder);
- GroupMemberships.registerTypeAdapters(builder);
- Verification.registerTypeAdapters(builder);
- builder.registerTypeAdapter(Credential.class,
- TypeAdapters.dispatch(
- ImmutableList.<Class<? extends Credential>>of(
- AuthnPrincipal.class,
- CredPassword.class,
- GroupMemberships.class)));
- }
-}
diff --git a/src/com/google/enterprise/secmgr/identity/GroupMemberships.java b/src/com/google/enterprise/secmgr/identity/GroupMemberships.java
deleted file mode 100644
index 2aa365f..0000000
--- a/src/com/google/enterprise/secmgr/identity/GroupMemberships.java
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.google.enterprise.secmgr.identity;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import com.google.enterprise.secmgr.common.Stringify;
-import com.google.enterprise.secmgr.config.CredentialTypeName;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A credential that contains a set of authentication group memberships
- * (such as a list of LDAP groups) to which the subject belongs.
- *
- * Similar to principals, the presence of a GroupMemberships instance does not
- * imply the credential has been verified; that is true only if the identity
- * has a verification that explicitly includes this GroupMemberships.
- * @see Verification
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class GroupMemberships extends AbstractCredential {
-
- @Nonnull private final ImmutableSet<String> groups;
-
- private GroupMemberships(Iterable<String> groups) {
- super();
- Preconditions.checkNotNull(groups);
- this.groups = ImmutableSet.copyOf(groups);
- Preconditions.checkArgument(!this.groups.isEmpty());
- }
-
- /**
- * Make a groups-membership set.
- *
- * @param groups The names of the groups.
- * @return An instance with the given names.
- */
- @Nonnull public static GroupMemberships make(Iterable<String> groups) {
- return new GroupMemberships(groups);
- }
-
- /**
- * Gets a set of the contained group names.
- *
- * @return The group's names as an immutable set of strings.
- */
- @Nonnull
- public ImmutableSet<String> getGroups() {
- return groups;
- }
-
- @Override
- public boolean isPublic() {
- return true;
- }
-
- @Override
- public CredentialTypeName getTypeName() {
- return CredentialTypeName.GROUPS;
- }
-
- @Override
- public boolean isVerifiable() {
- return true;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof GroupMemberships)) { return false; }
- GroupMemberships g = (GroupMemberships) object;
- return Objects.equal(groups, g.getGroups());
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(groups);
- }
-
- @Override
- public String toString() {
- return "{groups: " + Stringify.objects(groups) + "}";
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(GroupMemberships.class,
- ProxyTypeAdapter.make(GroupMemberships.class, LocalProxy.class));
- builder.registerTypeAdapter(new TypeToken<ImmutableSet<String>>() {}.getType(),
- TypeAdapters.immutableSet());
- }
-
- private static final class LocalProxy implements TypeProxy<GroupMemberships> {
- ImmutableSet<String> groups;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(GroupMemberships credential) {
- groups = credential.getGroups();
- }
-
- @Override
- public GroupMemberships build() {
- return make(groups);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/identity/Verification.java b/src/com/google/enterprise/secmgr/identity/Verification.java
deleted file mode 100644
index b070ad8..0000000
--- a/src/com/google/enterprise/secmgr/identity/Verification.java
+++ /dev/null
@@ -1,705 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.identity;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.enterprise.secmgr.common.SecurityManagerUtil;
-import com.google.enterprise.secmgr.common.Stringify;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-import org.joda.time.DateTimeUtils;
-import org.joda.time.format.DateTimeFormatter;
-import org.joda.time.format.ISODateTimeFormat;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnegative;
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The structure that holds results from credential verification.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class Verification {
-
- /**
- * A value for a verification expiration time that means the verification
- * doesn't expire.
- */
- public static final long NEVER_EXPIRES = -1;
-
- /**
- * A value for a verification expiration time that means the verification
- * expires when the current servlet request is finished.
- */
- public static final long EXPIRES_AFTER_REQUEST = -2;
-
- /**
- * Used internally to limit values accepted when making a verification.
- */
- public static final long MINIMUM_EXPIRATION_VALUE = -2;
-
- @Nonnull private final VerificationStatus status;
- private final long expirationTime;
- @Nonnull private final ImmutableSet<Credential> credentials;
-
- private Verification(VerificationStatus status, long expirationTime,
- Iterable<? extends Credential> credentials) {
- Preconditions.checkNotNull(status);
- Preconditions.checkArgument(expirationTime >= MINIMUM_EXPIRATION_VALUE);
- Preconditions.checkNotNull(credentials);
- this.status = status;
- this.expirationTime = expirationTime;
- this.credentials = ImmutableSet.copyOf(credentials);
- }
-
- /**
- * Gets a verification object with VERIFIED status and given credentials.
- *
- * @param expirationTime The expiration time of this verification.
- * @param credentials The credentials that the status applies to.
- * @return A verification with the given components.
- */
- public static Verification verified(long expirationTime,
- Iterable<? extends Credential> credentials) {
- return new Verification(VerificationStatus.VERIFIED, expirationTime, credentials);
- }
-
- /**
- * Gets a verification object with VERIFIED status and given credentials.
- *
- * @param expirationTime The expiration time of this verification.
- * @param credentials The credentials that the status applies to.
- * @return A verification with the given components.
- */
- public static Verification verified(long expirationTime, Credential... credentials) {
- return verified(expirationTime, Arrays.asList(credentials));
- }
-
- /**
- * Gets a verification object with REFUTED status and given credentials.
- *
- * @param credentials The credentials that the status applies to.
- * @return A verification with the given components.
- */
- public static Verification refuted(Iterable<? extends Credential> credentials) {
- return new Verification(VerificationStatus.REFUTED, EXPIRES_AFTER_REQUEST, credentials);
- }
-
- /**
- * Gets a verification object with REFUTED status and no credentials.
- *
- * @return A verification with the given components.
- */
- public static Verification refuted() {
- return refuted(ImmutableSet.<Credential>of());
- }
-
- @VisibleForTesting
- public static Verification make(VerificationStatus status, long expirationTime,
- Credential... credentials) {
- return new Verification(status, expirationTime, Arrays.asList(credentials));
- }
-
- /**
- * Gets the status of this verification.
- *
- * @return The verification's status.
- */
- @Nonnull
- public VerificationStatus getStatus() {
- return status;
- }
-
- /**
- * Are the credentials valid?
- *
- * @return True if the credentials were verified and found valid.
- */
- public boolean isVerified() {
- return status == VerificationStatus.VERIFIED;
- }
-
- /**
- * Are the credentials invalid?
- *
- * @return True if the credentials were verified and found invalid.
- */
- public boolean isRefuted() {
- return status == VerificationStatus.REFUTED;
- }
-
- /**
- * Is the verification status indeterminate?
- *
- * @return True if the credentials were verified with indeterminate result.
- */
- public boolean isIndeterminate() {
- return status == VerificationStatus.INDETERMINATE;
- }
-
- /**
- * Gets the expiration time for this verification. Positive is a time
- * comparable to {@link System#currentTimeMillis}, zero means "already
- * expired", negative means "never expires".
- *
- * @return The expiration time.
- */
- public long getExpirationTime() {
- return expirationTime;
- }
-
- /**
- * Has the verification expired based on the given time?
- *
- * @param now The reference time.
- * @return True if the verification has expired.
- */
- public boolean hasExpired(long now) {
- return expirationTime >= 0
- && !SecurityManagerUtil.isRemoteOnOrAfterTimeValid(expirationTime, now);
- }
-
- /**
- * Compares the expiration time of this verification with that of a given
- * verification. The result is a positive number if the expiration time of
- * this verification is later than that of the other; a negative number if
- * this time is earlier than that of the other; or zero if they are equal.
- *
- * @param other The verification to compare to.
- * @return The comparison result.
- */
- @CheckReturnValue
- public int compareExpirationTimes(Verification other) {
- return compareExpirationTimes(getExpirationTime(), other.getExpirationTime());
- }
-
- /**
- * Compares two expiration times.
- *
- * @param t1 The first expiration time.
- * @param t2 The second expiration time.
- * @return A negative number if {@code t1<t2}, a positive number if
- * {@code t1>t2}, or zero if {@code t1==t2}.
- * @throws IllegalArgumentException if either of the arguments is not
- * recognized as an expiration time.
- */
- @CheckReturnValue
- public static int compareExpirationTimes(long t1, long t2) {
- Preconditions.checkArgument(t1 >= MINIMUM_EXPIRATION_VALUE);
- Preconditions.checkArgument(t2 >= MINIMUM_EXPIRATION_VALUE);
- if (t1 == t2) { return 0; }
- if (t1 == NEVER_EXPIRES) { return 1; }
- if (t2 == NEVER_EXPIRES) { return -1; }
- if (t1 == 0) { return -1; }
- if (t2 == 0) { return 1; }
- if (t1 == EXPIRES_AFTER_REQUEST) { return -1; }
- if (t2 == EXPIRES_AFTER_REQUEST) { return 1; }
- return (t1 > t2) ? 1 : -1;
- }
-
- /**
- * Gets the minimum expiration time for some given verifications. Ignores any
- * verifications that don't satisfy {@link #isVerified}.
- *
- * @param verifications Some verifications to test.
- * @return The earliest expiration time for those verifications. Returns
- * {@link #NEVER_EXPIRES} if there are no verifications.
- */
- @CheckReturnValue
- public static long minimumExpirationTime(Iterable<Verification> verifications) {
- long expirationTime = NEVER_EXPIRES;
- for (Verification verification : verifications) {
- if (verification.isVerified()
- && compareExpirationTimes(verification.getExpirationTime(), expirationTime) < 0) {
- expirationTime = verification.getExpirationTime();
- }
- }
- return expirationTime;
- }
-
- /**
- * Gets the maximum expiration time for some given verifications. Ignores any
- * verifications that don't satisfy {@link #isVerified}.
- *
- * @param verifications Some verifications to test.
- * @return The latest expiration time for those verifications. Returns
- * {@code 0} if there are no verifications.
- */
- @CheckReturnValue
- public static long maximumExpirationTime(Iterable<Verification> verifications) {
- long expirationTime = 0;
- for (Verification verification : verifications) {
- if (verification.isVerified()
- && compareExpirationTimes(verification.getExpirationTime(), expirationTime) > 0) {
- expirationTime = verification.getExpirationTime();
- }
- }
- return expirationTime;
- }
-
- /**
- * Gets the credentials that were verified.
- *
- * @return An immutable set of the credentials that underwent verification.
- */
- @Nonnull
- public ImmutableSet<Credential> getCredentials() {
- return credentials;
- }
-
- /**
- * Does this verification contain a given credential?
- *
- * @param credential A credential to test for.
- * @return True if the given credential is contained.
- */
- public boolean containsCredential(Credential credential) {
- for (Credential v : credentials) {
- if (v.equals(credential)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Does this verification contain all of some given credentials?
- *
- * @param credentials Some credentials to test for.
- * @return True if all of the given credentials are contained.
- */
- public boolean containsAllCredentials(Iterable<? extends Credential> credentials) {
- for (Credential credential : credentials) {
- if (!containsCredential(credential)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Does this verification contain any of some given credentials?
- *
- * @param credentials Some credentials to test for.
- * @return True if any of the given credentials are contained.
- */
- public boolean containsAnyCredential(Iterable<? extends Credential> credentials) {
- for (Credential credential : credentials) {
- if (containsCredential(credential)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) { return true; }
- if (!(object instanceof Verification)) { return false; }
- Verification verification = (Verification) object;
- return Objects.equal(status, verification.getStatus())
- && Objects.equal(credentials, verification.getCredentials());
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(status, credentials);
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("{Verification: status=");
- builder.append(status);
- builder.append("; ");
- if (expirationTime == NEVER_EXPIRES) {
- builder.append("never expires");
- } else if (expirationTime == EXPIRES_AFTER_REQUEST) {
- builder.append("expires after request");
- } else {
- builder.append("expires at ");
- builder.append(ISO8601_FORMAT.print(expirationTime));
- }
- if (!credentials.isEmpty()) {
- builder.append("; credentials ");
- builder.append(Stringify.objects(credentials));
- }
- builder.append("}");
- return builder.toString();
- }
-
- private static final DateTimeFormatter ISO8601_FORMAT = ISODateTimeFormat.dateTime();
-
- /**
- * Gets a predicate that compares a verification's status to a given value.
- *
- * @param status A status to test for.
- * @return The corresponding predicate.
- */
- @CheckReturnValue
- @Nonnull
- public static Predicate<Verification> getStatusPredicate(VerificationStatus status) {
- return Predicates.compose(Predicates.equalTo(status), GET_STATUS_FUNCTION);
- }
-
- private static final Function<Verification, VerificationStatus> GET_STATUS_FUNCTION =
- new Function<Verification, VerificationStatus>() {
- @Override
- public VerificationStatus apply(Verification v) {
- return v.getStatus();
- }
- };
-
- /**
- * Gets a predicate that tests whether a given verification has status
- * {@link VerificationStatus#VERIFIED}.
- *
- * @return The predicate.
- */
- @CheckReturnValue
- @Nonnull
- public static Predicate<Verification> isVerifiedPredicate() {
- return IS_VERIFIED_PREDICATE;
- }
-
- private static final Predicate<Verification> IS_VERIFIED_PREDICATE
- = getStatusPredicate(VerificationStatus.VERIFIED);
-
- /**
- * Gets a predicate that tests whether a given verification has status
- * {@link VerificationStatus#REFUTED}.
- *
- * @return The predicate.
- */
- @CheckReturnValue
- @Nonnull
- public static Predicate<Verification> isRefutedPredicate() {
- return IS_REFUTED_PREDICATE;
- }
-
- private static final Predicate<Verification> IS_REFUTED_PREDICATE
- = getStatusPredicate(VerificationStatus.REFUTED);
-
- /**
- * Gets a predicate that tests whether a verification is expired
- *
- * @param time The reference time for the expiration.
- * @return The corresponding predicate.
- */
- @CheckReturnValue
- @Nonnull
- public static Predicate<Verification> getExpirationPredicate(final long time) {
- return new Predicate<Verification>() {
- @Override
- public boolean apply(Verification v) {
- return v.hasExpired(time);
- }
- };
- }
-
- /**
- * Gets a predicate that tests whether a verification should expire after the
- * current request.
- *
- * @return The predicate.
- */
- @CheckReturnValue
- @Nonnull
- public static Predicate<Verification> getRequestExpirationPredicate() {
- return REQUEST_EXPIRATION_PREDICATE;
- }
-
- private static final Function<Verification, Long> GET_EXPIRATION_TIME_FUNCTION =
- new Function<Verification, Long>() {
- @Override
- public Long apply(Verification v) {
- return v.getExpirationTime();
- }
- };
-
- private static final Predicate<Verification> REQUEST_EXPIRATION_PREDICATE =
- Predicates.compose(Predicates.equalTo(EXPIRES_AFTER_REQUEST), GET_EXPIRATION_TIME_FUNCTION);
-
- /**
- * Gets a predicate that invokes the {@link #containsCredential} method on a
- * given verification.
- *
- * @param credential The credential to test for.
- * @return The corresponding predicate.
- */
- @CheckReturnValue
- @Nonnull
- public static Predicate<Verification> getContainsCredentialPredicate(
- final Credential credential) {
- Preconditions.checkNotNull(credential);
- return new Predicate<Verification>() {
- @Override
- public boolean apply(Verification verification) {
- return verification.containsCredential(credential);
- }
- };
- }
-
- /**
- * Gets a predicate that invokes the {@link #containsAllCredentials} method on
- * a given verification.
- *
- * @param credentials The credentials to test for.
- * @return The corresponding predicate.
- */
- @CheckReturnValue
- @Nonnull
- public static Predicate<Verification> getContainsAllCredentialsPredicate(
- final Iterable<? extends Credential> credentials) {
- Preconditions.checkNotNull(credentials);
- return new Predicate<Verification>() {
- @Override
- public boolean apply(Verification verification) {
- return verification.containsAllCredentials(credentials);
- }
- };
- }
-
- /**
- * Gets a predicate that invokes the {@link #containsAllCredentials} method on
- * a given verification.
- *
- * @param credentials The credentials to test for.
- * @return The corresponding predicate.
- */
- @CheckReturnValue
- @Nonnull
- public static Predicate<Verification> getContainsAllCredentialsPredicate(
- Credential... credentials) {
- return getContainsAllCredentialsPredicate(Arrays.asList(credentials));
- }
-
- /**
- * Gets a predicate that invokes the {@link #containsAnyCredential} method on
- * a given verification.
- *
- * @param credentials The credentials to test for.
- * @return The corresponding predicate.
- */
- @CheckReturnValue
- @Nonnull
- public static Predicate<Verification> getContainsAnyCredentialPredicate(
- final Iterable<? extends Credential> credentials) {
- return new Predicate<Verification>() {
- public boolean apply(Verification v) {
- return v.containsAnyCredential(credentials);
- }
- };
- }
-
- /**
- * Gets a predicate that invokes the {@link #containsAnyCredential} method on
- * a given verification.
- *
- * @param credentials The credentials to test for.
- * @return The corresponding predicate.
- */
- @CheckReturnValue
- @Nonnull
- public static Predicate<Verification> getContainsAnyCredentialPredicate(
- Credential... credentials) {
- return getContainsAnyCredentialPredicate(Arrays.asList(credentials));
- }
-
- /**
- * Determines the verification status from a set of verifications.
- *
- * @param verifications The set of verifications to check.
- * @return The aggregate status of the verifications.
- */
- @CheckReturnValue
- @Nonnull
- public static VerificationStatus getStatus(Iterable<Verification> verifications) {
- VerificationStatus result = VerificationStatus.INDETERMINATE;
- for (Verification verification : verifications) {
- if (verification.isRefuted()) {
- return VerificationStatus.REFUTED;
- }
- if (verification.isVerified()) {
- result = VerificationStatus.VERIFIED;
- }
- }
- return result;
- }
-
- /**
- * Determines the joint verification status for some given credentials from a
- * set of verifications.
- *
- * @param verifications The set of verifications to check.
- * @param credentials The set of credentials to look for.
- * @return The joint verification status of the relevant verifications.
- */
- @CheckReturnValue
- @Nonnull
- public static VerificationStatus getStatus(Iterable<Verification> verifications,
- Iterable<? extends Credential> credentials) {
- return getStatus(
- Iterables.filter(verifications,
- getContainsAllCredentialsPredicate(credentials)));
- }
-
- /**
- * Determines whether one of a set of verifications has VERIFIED state.
- *
- * @param verifications The set of verifications to check.
- * @return True if there's at least one VERIFIED element in the set.
- */
- public static boolean isVerified(Iterable<Verification> verifications) {
- return getStatus(verifications) == VerificationStatus.VERIFIED;
- }
-
- /**
- * Determines whether one of a set of verifications has REFUTED state.
- *
- * @param verifications The set of verifications to check.
- * @return True if there's at least one REFUTED element in the set.
- */
- public static boolean isRefuted(Iterable<Verification> verifications) {
- return getStatus(verifications) == VerificationStatus.REFUTED;
- }
-
- /**
- * Determines whether none of a set of verifications has VERIFIED or REFUTED
- * state.
- *
- * @param verifications The set of verifications to check.
- * @return False if there's at least one VERIFIED or REFUTED element in the
- * set.
- */
- public static boolean isIndeterminate(Iterable<Verification> verifications) {
- return getStatus(verifications) == VerificationStatus.INDETERMINATE;
- }
-
- /**
- * Determines whether one of a set of verifications has VERIFIED state and
- * contains all of the given credentials.
- *
- * @param verifications The set of verifications to check.
- * @param credentials The set of credentials to look for.
- * @return True if there's at least one VERIFIED element in the containing all
- * of the credentials.
- */
- public static boolean isVerified(Iterable<Verification> verifications,
- Iterable<Credential> credentials) {
- return getStatus(verifications, credentials) == VerificationStatus.VERIFIED;
- }
-
- /**
- * Determines whether one of a set of verifications has REFUTED state and
- * contains all of the given credentials.
- *
- * @param verifications The set of verifications to check.
- * @param credentials The set of credentials to look for.
- * @return True if there's at least one REFUTED element in the containing all
- * of the credentials.
- */
- public static boolean isRefuted(Iterable<Verification> verifications,
- Iterable<Credential> credentials) {
- return getStatus(verifications, credentials) == VerificationStatus.REFUTED;
- }
-
- /**
- * Gets the newest of a set of verifications; in other words, the verification
- * with the latest expiration time.
- *
- * @param verifications The verifications to test.
- * @return The newest of the given verifications, or {@code null} if the given
- * set is empty.
- */
- @CheckReturnValue
- @Nonnull
- public static Verification newestOf(Iterable<Verification> verifications) {
- Verification result = null;
- for (Verification verification : verifications) {
- if (result == null || verification.compareExpirationTimes(result) > 0) {
- result = verification;
- }
- }
- return result;
- }
-
- /**
- * Removes any expired verifications from a given collection.
- *
- * @param verifications A collection of verifications to process.
- * @param timeStamp A reference time for determining expiration.
- */
- public static void expireVerifications(Collection<Verification> verifications,
- @Nonnegative long timeStamp) {
- Iterables.removeIf(verifications, getExpirationPredicate(timeStamp));
- }
-
- /**
- * Removes any expired verifications from a given collection. Uses the
- * current time as a reference.
- *
- * @param verifications A collection of verifications to process.
- */
- public static void expireVerifications(Collection<Verification> verifications) {
- expireVerifications(verifications, DateTimeUtils.currentTimeMillis());
- }
-
- static void registerTypeAdapters(GsonBuilder builder) {
- builder.registerTypeAdapter(Verification.class,
- ProxyTypeAdapter.make(Verification.class, LocalProxy.class));
- builder.registerTypeAdapter(new TypeToken<ImmutableSet<Credential>>() {}.getType(),
- TypeAdapters.immutableSet());
- }
-
- private static final class LocalProxy implements TypeProxy<Verification> {
- VerificationStatus status;
- long expirationTime;
- ImmutableSet<Credential> credentials;
-
- @SuppressWarnings("unused")
- LocalProxy() {
- }
-
- @SuppressWarnings("unused")
- LocalProxy(Verification verification) {
- status = verification.getStatus();
- expirationTime = verification.getExpirationTime();
- credentials = verification.getCredentials();
- }
-
- @Override
- public Verification build() {
- return new Verification(status, expirationTime, credentials);
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/identity/VerificationStatus.java b/src/com/google/enterprise/secmgr/identity/VerificationStatus.java
deleted file mode 100644
index 4ddaf2c..0000000
--- a/src/com/google/enterprise/secmgr/identity/VerificationStatus.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.identity;
-
-/**
- * The status code attached to a {@link Verification} indicating the disposition
- * of the verification.
- */
-public enum VerificationStatus {
- VERIFIED, // recognized by IdP
- REFUTED, // unrecognized by IdP
- INDETERMINATE // unable to verify
-}
diff --git a/src/com/google/enterprise/secmgr/modules/SamlClient.java b/src/com/google/enterprise/secmgr/modules/SamlClient.java
index 85ebae5..28880e2 100644
--- a/src/com/google/enterprise/secmgr/modules/SamlClient.java
+++ b/src/com/google/enterprise/secmgr/modules/SamlClient.java
@@ -14,7 +14,6 @@
package com.google.enterprise.secmgr.modules;
-import static com.google.enterprise.secmgr.saml.OpenSamlUtil.getMetadataSignaturePolicyRule;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.initializeLocalEntity;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.initializePeerEntity;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeAction;
@@ -22,9 +21,7 @@
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeAuthnRequest;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeAuthzDecisionQuery;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeSamlMessageContext;
-import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeStaticSecurityPolicyResolver;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeSubject;
-import static com.google.enterprise.secmgr.saml.OpenSamlUtil.peerSupportsSignatureVerification;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.runDecoder;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.runEncoder;
import static org.opensaml.common.xml.SAMLConstants.SAML20P_NS;
@@ -33,24 +30,19 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
-//import com.google.enterprise.secmgr.authncontroller.AuthnSession;
import com.google.enterprise.secmgr.common.AuthzStatus;
-import com.google.enterprise.secmgr.common.HttpUtil;
-//import com.google.enterprise.secmgr.common.ServletBase;
import com.google.enterprise.secmgr.http.HttpClientInterface;
import com.google.enterprise.secmgr.http.HttpExchange;
import com.google.enterprise.secmgr.saml.HTTPSOAP11MultiContextDecoder;
import com.google.enterprise.secmgr.saml.HTTPSOAP11MultiContextEncoder;
import com.google.enterprise.secmgr.saml.HttpExchangeToInTransport;
import com.google.enterprise.secmgr.saml.HttpExchangeToOutTransport;
-import com.google.enterprise.secmgr.saml.MetadataEditor;
import com.google.enterprise.secmgr.saml.SamlLogUtil;
import org.joda.time.DateTime;
import org.opensaml.common.SAMLObject;
import org.opensaml.common.binding.SAMLMessageContext;
import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.binding.decoding.HTTPPostDecoder;
import org.opensaml.saml2.binding.decoding.HTTPSOAP11Decoder;
import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder;
import org.opensaml.saml2.binding.encoding.HTTPSOAP11Encoder;
@@ -75,16 +67,13 @@
import org.opensaml.util.URLBuilder;
import org.opensaml.ws.message.encoder.MessageEncoder;
import org.opensaml.ws.message.encoder.MessageEncodingException;
-import org.opensaml.ws.security.provider.MandatoryAuthenticatedMessageRule;
-import org.opensaml.ws.security.provider.MandatoryIssuerRule;
import org.opensaml.ws.transport.http.HTTPInTransport;
import org.opensaml.ws.transport.http.HTTPOutTransport;
-import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
-import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
import org.opensaml.xml.security.credential.Credential;
import org.opensaml.xml.util.Pair;
import java.io.IOException;
+import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.Collection;
@@ -94,8 +83,6 @@
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
/**
* A library implementing most of the functionality of a SAML service provider.
@@ -200,7 +187,7 @@
* @return The assertion consumer service descriptor.
*/
public AssertionConsumerService getPostAssertionConsumerService() {
- return getAssertionConsumerService(MetadataEditor.SAML_BINDING_HTTP_POST);
+ return getAssertionConsumerService(SAMLConstants.SAML2_POST_BINDING_URI);
}
/**
@@ -209,7 +196,7 @@
* @return The assertion consumer service descriptor.
*/
public AssertionConsumerService getArtifactAssertionConsumerService() {
- return getAssertionConsumerService(MetadataEditor.SAML_BINDING_HTTP_ARTIFACT);
+ return getAssertionConsumerService(SAMLConstants.SAML2_ARTIFACT_BINDING_URI);
}
private AssertionConsumerService getAssertionConsumerService(String binding) {
@@ -269,56 +256,6 @@
}
/**
- * Decode a SAML response sent via the POST binding.
- *
- * @param request The HTTP request containing the encoded response.
- * @return The decoded response, or null if there was an error decoding the message. In
- * this case, a log file entry is generated, so the caller doesn't need to know the
- * details of the failure.
- * @throws IOException for various errors related to session and metadata.
- */
- /*
- // Commented out to prevent pulling in AuthnSession.
- public Response decodePostResponse(HttpServletRequest request)
- throws IOException {
- AuthnSession session = AuthnSession.getInstance(request);
- if (session == null) {
- return null;
- }
- SAMLMessageContext<Response, SAMLObject, NameID> context =
- makeSamlMessageContext();
-
- initializeLocalEntity(context, localEntity, localEntity.getSPSSODescriptor(SAML20P_NS));
- initializePeerEntity(context, peerEntity, peerEntity.getIDPSSODescriptor(SAML20P_NS),
- SingleSignOnService.DEFAULT_ELEMENT_NAME,
- SAML2_REDIRECT_BINDING_URI);
-
- if (!peerSupportsSignatureVerification(context)) {
- LOGGER.warning("SAML POST peer not configured for signature verification");
- return null;
- }
-
- // Create a security policy to check the response signature. Works only
- // with certificates that are stored in the metadata.
- context.setSecurityPolicyResolver(
- makeStaticSecurityPolicyResolver(
- getMetadataSignaturePolicyRule(request),
- // Requires an <Issuer>:
- new MandatoryIssuerRule(),
- // Requires that the message be authenticated:
- new MandatoryAuthenticatedMessageRule()));
-
- context.setInboundMessageTransport(new HttpServletRequestAdapter(request));
- if (!runDecoder(new HTTPPostDecoder(), context, session, "client identity provider")) {
- return null;
- }
-
- Response samlResponse = context.getInboundSAMLMessage();
- Preconditions.checkNotNull(samlResponse, "Decoded SAML response is null");
- return samlResponse;
- }*/
-
- /**
* Decode a SAML response sent via the artifact binding.
*
* @param request The HTTP request containing the artifact.
@@ -405,7 +342,7 @@
// Do HTTP exchange.
int status = exchange.exchange();
- if (status != HttpServletResponse.SC_OK) {
+ if (status != HttpURLConnection.HTTP_OK) {
LOGGER.warning("Incorrect HTTP status: " + status);
return null;
}
@@ -448,7 +385,7 @@
// Do HTTP exchange
int status = exchange.exchange();
- if (!HttpUtil.isGoodHttpStatus(status)) {
+ if (!isGoodHttpStatus(status)) {
throw new IOException("Incorrect HTTP status: " + status);
}
@@ -511,7 +448,7 @@
// Do HTTP exchange
int status = exchange.exchange();
- if (!HttpUtil.isGoodHttpStatus(status)) {
+ if (!isGoodHttpStatus(status)) {
throw new IOException("Incorrect HTTP status: " + status);
}
@@ -678,4 +615,9 @@
return builder.buildURL();
}
}
+
+ public static boolean isGoodHttpStatus(int status) {
+ return status == HttpURLConnection.HTTP_OK
+ || status == HttpURLConnection.HTTP_PARTIAL;
+ }
}
diff --git a/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextDecoder.java b/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextDecoder.java
index b997127..5021b89 100644
--- a/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextDecoder.java
+++ b/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextDecoder.java
@@ -27,11 +27,11 @@
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.parse.ParserPool;
import org.opensaml.xml.util.DatatypeHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.xml.namespace.QName;
@@ -42,7 +42,7 @@
public class HTTPSOAP11MultiContextDecoder extends BaseSAML2MessageDecoder {
/** Class logger. */
- private final Logger log = LoggerFactory.getLogger(HTTPSOAP11MultiContextDecoder.class);
+ private static final Logger log = Logger.getLogger(HTTPSOAP11MultiContextDecoder.class.getName());
/** QNames of understood SOAP headers. */
private final List<QName> understoodHeaders = new ArrayList<QName>();
@@ -102,7 +102,6 @@
@Override
protected void doDecode(MessageContext messageContext) throws MessageDecodingException {
if (!(messageContext instanceof SAMLMessageContext<?, ?, ?>)) {
- log.error("Invalid message context type, this decoder only support SAMLMessageContext");
throw new MessageDecodingException(
"Invalid message context type, this decoder only support SAMLMessageContext");
}
@@ -116,10 +115,9 @@
}
if (soapBodyChildren.size() < 1) {
- log.error("Unexpected number of children in the SOAP body, " + soapBodyChildren.size()
- + ". Unable to extract SAML message");
throw new MessageDecodingException(
- "Unexpected number of children in the SOAP body, unable to extract SAML message");
+ "Unexpected number of children in the SOAP body, " + soapBodyChildren.size()
+ + ". Unable to extract SAML message");
}
if (thisChild >= soapBodyChildren.size()) {
@@ -132,16 +130,15 @@
thisChild++;
if (!(incomingMessage instanceof SAMLObject)) {
- log.error("Unexpected SOAP body content. Expected a SAML request but recieved {}",
- incomingMessage.getElementQName());
throw new MessageDecodingException(
"Unexpected SOAP body content. Expected a SAML request but recieved "
+ incomingMessage.getElementQName());
}
SAMLObject samlMessage = (SAMLObject) incomingMessage;
- log.debug("Decoded SOAP messaged which included SAML message of type {}",
- samlMessage.getElementQName());
+ log.log(Level.FINE,
+ "Decoded SOAP messaged which included SAML message of type {}",
+ samlMessage.getElementQName());
samlMsgCtx.setInboundSAMLMessage(samlMessage);
populateMessageContext(samlMsgCtx);
@@ -183,8 +180,6 @@
private void start(SAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> samlMsgCtx)
throws MessageDecodingException {
if (!(samlMsgCtx.getInboundMessageTransport() instanceof HTTPInTransport)) {
- log.error(
- "Invalid inbound message transport type, this decoder only support HTTPInTransport");
throw new MessageDecodingException(
"Invalid inbound message transport type, this decoder only support HTTPInTransport");
}
@@ -195,7 +190,7 @@
"This message deocoder only supports the HTTP POST method");
}
- log.debug("Unmarshalling SOAP message");
+ log.fine("Unmarshalling SOAP message");
soapMessage = Envelope.class.cast(unmarshallMessage(inTransport.getIncomingStream()));
Header messageHeader = soapMessage.getHeader();
diff --git a/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextEncoder.java b/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextEncoder.java
index f982483..0794408 100644
--- a/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextEncoder.java
+++ b/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextEncoder.java
@@ -28,14 +28,13 @@
import org.opensaml.ws.transport.http.HTTPTransportUtils;
import org.opensaml.xml.XMLObjectBuilderFactory;
import org.opensaml.xml.util.XMLHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
+import java.util.logging.Logger;
/**
* SAML 2.0 SOAP 1.1 over HTTP MultiContext binding encoder.
@@ -48,7 +47,7 @@
private HTTPOutTransport outTransport;
/** Class logger. */
- private final Logger log = LoggerFactory.getLogger(HTTPSOAP11MultiContextEncoder.class);
+ private static final Logger log = Logger.getLogger(HTTPSOAP11MultiContextEncoder.class.getName());
/** Constructor. */
public HTTPSOAP11MultiContextEncoder() {
@@ -78,7 +77,6 @@
@Override
protected void doEncode(MessageContext messageContext) throws MessageEncodingException {
if (!(messageContext instanceof SAMLMessageContext<?, ?, ?>)) {
- log.error("Invalid message context type, this encoder only supports SAMLMessageContext");
throw new MessageEncodingException(
"Invalid message context type, this encoder only supports SAMLMessageContext");
}
@@ -87,8 +85,6 @@
(SAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>) messageContext;
if (!(messageContext.getOutboundMessageTransport() instanceof HTTPOutTransport)) {
- log.error(
- "Invalid outbound message transport type, this encoder only supports HTTPOutTransport");
throw new MessageEncodingException(
"Invalid outbound message transport type, this encoder only supports HTTPOutTransport");
}
@@ -106,9 +102,7 @@
signMessage(samlMsgCtx);
samlMsgCtx.setOutboundMessage(envelope);
- if (log.isDebugEnabled()) {
- log.debug("Adding SAML message to the SOAP message's body");
- }
+ log.fine("Adding SAML message to the SOAP message's body");
body.getUnknownXMLObjects().add(samlMessage);
}
@@ -124,10 +118,8 @@
XMLHelper.writeNode(envelopeElem, out);
out.flush();
} catch (UnsupportedEncodingException e) {
- log.error("JVM does not support required UTF-8 encoding");
throw new MessageEncodingException("JVM does not support required UTF-8 encoding");
} catch (IOException e) {
- log.error("Unable to write message content to outbound stream", e);
throw new MessageEncodingException("Unable to write message content to outbound stream", e);
}
}
@@ -136,9 +128,7 @@
* Builds the SOAP message to be encoded.
*/
protected void buildSOAPMessage() {
- if (log.isDebugEnabled()) {
- log.debug("Building SOAP message");
- }
+ log.fine("Building SOAP message");
XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
@SuppressWarnings("unchecked")
diff --git a/src/com/google/enterprise/secmgr/saml/Metadata.java b/src/com/google/enterprise/secmgr/saml/Metadata.java
deleted file mode 100644
index df06562..0000000
--- a/src/com/google/enterprise/secmgr/saml/Metadata.java
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2008 Google Inc.
-//
-// 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.google.enterprise.secmgr.saml;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Maps;
-import com.google.enterprise.secmgr.common.FileUtil;
-import com.google.enterprise.secmgr.common.SecurityManagerUtil;
-import com.google.enterprise.secmgr.common.XmlUtil;
-import com.google.enterprise.secmgr.config.ConfigSingleton;
-
-import org.opensaml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.provider.AbstractObservableMetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
-import org.opensaml.saml2.metadata.provider.ObservableMetadataProvider;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.io.MarshallingException;
-import org.opensaml.xml.io.UnmarshallingException;
-import org.w3c.dom.CDATASection;
-import org.w3c.dom.Comment;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.EntityReference;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.ProcessingInstruction;
-import org.w3c.dom.Text;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Map;
-import java.util.logging.Logger;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * An abstract interface to the SAML metadata configuration. Tracks a given
- * metadata file and keeps it up to date. Also rewrites the metadata so it uses
- * the correct hostname.
- */
-@ThreadSafe
-public class Metadata {
-
- private static final Logger LOGGER = Logger.getLogger(Metadata.class.getName());
-
- @GuardedBy("itself")
- private static final Map<String, Metadata> perHostMap = Maps.newHashMap();
- private static File metadataFile = null;
-
- private final MetadataProvider provider;
-
- private Metadata(String urlPrefix)
- throws IOException {
- try {
- this.provider = new MyProvider(
- OpenSamlUtil.getMetadataFromFile(
- (metadataFile != null)
- ? metadataFile
- : FileUtil.getContextFile(ConfigSingleton.getSamlMetadataFilename())),
- urlPrefix, SecurityManagerUtil.getGsaEntConfigName());
- } catch (MetadataProviderException e) {
- throw new IOException(e);
- }
- }
-
- @VisibleForTesting
- static void setMetadataFile(File metadataFile) {
- Metadata.metadataFile = metadataFile;
- }
-
- @VisibleForTesting
- public static Metadata getInstance(String host)
- throws IOException {
- return getInstance("http", host);
- }
-
- public static Metadata getInstance(URL url)
- throws IOException {
- return getInstance(url.getProtocol(), url.getHost());
- }
-
- public static Metadata getInstance(String protocol, String host)
- throws IOException {
- String urlPrefix = protocol + "://" + host;
- Metadata result;
- synchronized (perHostMap) {
- result = perHostMap.get(urlPrefix);
- if (result == null) {
- result = new Metadata(urlPrefix);
- perHostMap.put(urlPrefix, result);
- }
- }
- return result;
- }
-
- public MetadataProvider getProvider() {
- return provider;
- }
-
- public EntitiesDescriptor getMetadata() throws IOException {
- XMLObject root;
- try {
- root = provider.getMetadata();
- } catch (MetadataProviderException e) {
- throw new IOException(e);
- }
- if (root instanceof EntitiesDescriptor) {
- return (EntitiesDescriptor) root;
- }
- throw new IOException("Malformed SAML metadata");
- }
-
- public EntityDescriptor getEntity(String id) throws IOException {
- EntityDescriptor entity;
- try {
- entity = provider.getEntityDescriptor(id);
- } catch (MetadataProviderException e) {
- throw new IOException(e);
- }
- if (entity == null) {
- throw new IllegalArgumentException("Unknown entity ID: " + id);
- }
- return entity;
- }
-
- public EntityDescriptor getSmEntity() throws IOException {
- for (EntityDescriptor e : getMetadata().getEntityDescriptors()) {
- if (MetadataEditor.SECMGR_ID_FOR_ENTITY.equals(e.getID())) {
- return e;
- }
- }
- throw new IllegalStateException("Can't find security manager's entity descriptor");
- }
-
- public String getSmEntityId() throws IOException {
- return getSmEntity().getEntityID();
- }
-
- /**
- * This class implements a wrapper around an OpenSAML
- * ObservableMetadataProvider that customizes the metadata for a particular
- * host. When the metadata is updated, as when the configuration file is
- * changed, this provider notices that, gets the updated metadata, and
- * customizes it. To speed things up a bit, the customized metadata is
- * cached, so it need not be customized every time.
- */
- private static class MyProvider
- extends AbstractObservableMetadataProvider
- implements ObservableMetadataProvider.Observer {
-
- private final ObservableMetadataProvider wrappedProvider;
- private final String urlPrefix;
- private final String gsaEntConfigName;
- private XMLObject savedMetadata;
-
- public MyProvider(ObservableMetadataProvider wrappedProvider,
- String urlPrefix, String gsaEntConfigName) {
- super();
- this.wrappedProvider = wrappedProvider;
- this.urlPrefix = urlPrefix;
- this.gsaEntConfigName = gsaEntConfigName;
- savedMetadata = null;
- wrappedProvider.getObservers().add(this);
- }
-
- public synchronized void onEvent(MetadataProvider provider) {
- LOGGER.info("Clearing cached metadata");
- savedMetadata = null;
- emitChangeEvent();
- }
-
- public synchronized XMLObject getMetadata() throws MetadataProviderException {
- // This will call onEvent if the file has changed:
- XMLObject rawMetadata = wrappedProvider.getMetadata();
- if (savedMetadata == null) {
- try {
- savedMetadata = OpenSamlUtil.unmarshallXmlObject(
- substituteTopLevel(
- OpenSamlUtil.marshallXmlObject(rawMetadata)));
- } catch (MarshallingException e) {
- throw new MetadataProviderException(e);
- } catch (UnmarshallingException e) {
- throw new MetadataProviderException(e);
- }
- }
- return savedMetadata;
- }
-
- private Element substituteTopLevel(Element element) {
- Document doc = XmlUtil.getInstance()
- .makeDocument(element.getNamespaceURI(), element.getTagName(), null);
- Element newElement = doc.getDocumentElement();
- substituteInNodeChildren(element, newElement, doc);
- return newElement;
- }
-
- private void substituteInNodeChildren(Node node, Node newNode, Document doc) {
- if (node instanceof Element) {
- NamedNodeMap attrs = node.getAttributes();
- NamedNodeMap newAttrs = newNode.getAttributes();
- for (int i = 0; i < attrs.getLength(); i++) {
- Node attr = attrs.item(i);
- Node newAttr = doc.createAttributeNS(attr.getNamespaceURI(), attr.getNodeName());
- newAttr.setNodeValue(substituteInString(attr.getNodeValue()));
- newAttrs.setNamedItemNS(newAttr);
- }
- }
- for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
- Node newChild = substituteInNode(child, doc);
- substituteInNodeChildren(child, newChild, doc);
- newNode.appendChild(newChild);
- }
- }
-
- private Node substituteInNode(Node node, Document doc) {
- if (node instanceof Element) {
- return doc.createElementNS(node.getNamespaceURI(), node.getNodeName());
- } else if (node instanceof Text) {
- return doc.createTextNode(substituteInString(node.getNodeValue()));
- } else if (node instanceof CDATASection) {
- return doc.createCDATASection(node.getNodeValue());
- } else if (node instanceof Comment) {
- return doc.createComment(node.getNodeValue());
- } else if (node instanceof EntityReference) {
- return doc.createEntityReference(node.getNodeName());
- } else if (node instanceof ProcessingInstruction) {
- return doc.createProcessingInstruction(node.getNodeName(), node.getNodeValue());
- } else {
- throw new IllegalArgumentException("Unknown node type: " + node.getNodeType());
- }
- }
-
- private String substituteInString(String original) {
- if (original == null) { return original; }
- String pattern = "https://" + MetadataEditor.GSA_HOST_MARKER;
- if (original.startsWith(pattern)) {
- return original.replace(pattern, urlPrefix);
- }
- pattern = "http://" + MetadataEditor.GSA_HOST_MARKER;
- if (original.startsWith(pattern)) {
- return original.replace(pattern, urlPrefix);
- }
- if (original.contains(MetadataEditor.GSA_ENT_CONFIG_NAME_MARKER)) {
- return original.replace(MetadataEditor.GSA_ENT_CONFIG_NAME_MARKER, gsaEntConfigName);
- }
- return original;
- }
- }
-}
diff --git a/src/com/google/enterprise/secmgr/saml/MetadataEditor.java b/src/com/google/enterprise/secmgr/saml/MetadataEditor.java
deleted file mode 100644
index 933ed08..0000000
--- a/src/com/google/enterprise/secmgr/saml/MetadataEditor.java
+++ /dev/null
@@ -1,1069 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.google.enterprise.secmgr.saml;
-
-import static com.google.enterprise.secmgr.common.XmlUtil.countChildElements;
-import static com.google.enterprise.secmgr.common.XmlUtil.findChildComments;
-import static com.google.enterprise.secmgr.common.XmlUtil.findChildElement;
-import static com.google.enterprise.secmgr.common.XmlUtil.getElementsByQname;
-import static com.google.enterprise.secmgr.common.XmlUtil.makeCommentChild;
-import static com.google.enterprise.secmgr.common.XmlUtil.makeElement;
-import static com.google.enterprise.secmgr.common.XmlUtil.makeElementChild;
-import static com.google.enterprise.secmgr.common.XmlUtil.makeTextChild;
-import static com.google.enterprise.secmgr.common.XmlUtil.makeTextElementChild;
-import static com.google.enterprise.secmgr.common.XmlUtil.setConfigParams;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import com.google.enterprise.secmgr.common.XmlUtil;
-
-import org.w3c.dom.Comment;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.Writer;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.annotation.concurrent.Immutable;
-import javax.xml.crypto.dsig.XMLSignature;
-import javax.xml.namespace.QName;
-
-/**
- * Utilities for editing SAML metadata files.
- */
-@Immutable
-public class MetadataEditor {
- private static final Logger LOGGER = Logger.getLogger(MetadataEditor.class.getName());
-
- // SAML metadata elements.
- public static final String SAML_MD_NS = "urn:oasis:names:tc:SAML:2.0:metadata";
-
- private static QName mdName(String localPart) {
- return new QName(SAML_MD_NS, localPart);
- }
-
- public static final QName SAML_DESCRIPTOR_ENTITIES = mdName("EntitiesDescriptor");
- public static final QName SAML_DESCRIPTOR_ENTITY = mdName("EntityDescriptor");
- public static final QName SAML_DESCRIPTOR_IDP_SSO = mdName("IDPSSODescriptor");
- public static final QName SAML_DESCRIPTOR_KEY = mdName("KeyDescriptor");
- public static final QName SAML_DESCRIPTOR_PDP = mdName("PDPDescriptor");
- public static final QName SAML_DESCRIPTOR_SP_SSO = mdName("SPSSODescriptor");
- public static final QName SAML_ORGANIZATION = mdName("Organization");
- public static final QName SAML_ORGANIZATION_DISPLAY_NAME = mdName("OrganizationDisplayName");
- public static final QName SAML_ORGANIZATION_NAME = mdName("OrganizationName");
- public static final QName SAML_ORGANIZATION_URL = mdName("OrganizationURL");
- public static final QName SAML_SERVICE_ARTIFACT_RESOLUTION = mdName("ArtifactResolutionService");
- public static final QName SAML_SERVICE_ASSERTION_CONSUMER = mdName("AssertionConsumerService");
- public static final QName SAML_SERVICE_AUTHZ = mdName("AuthzService");
- public static final QName SAML_SERVICE_SINGLE_SIGN_ON = mdName("SingleSignOnService");
-
- // SAML metadata attributes.
- public static final String SAML_ATTR_BINDING = "Binding";
- public static final String SAML_ATTR_CACHE_DURATION = "cacheDuration";
- public static final String SAML_ATTR_ENTITY_ID = "entityID";
- public static final String SAML_ATTR_INDEX = "index";
- public static final String SAML_ATTR_IS_DEFAULT = "isDefault";
- public static final String SAML_ATTR_LOCATION = "Location";
- public static final String SAML_ATTR_NAME = "Name";
- public static final String SAML_ATTR_PROTOCOL_SUPPORT_ENUMERATION = "protocolSupportEnumeration";
- public static final String SAML_ATTR_USE = "use";
- public static final String XML_ATTR_ID = "ID";
-
- // SAML metadata attribute values.
- public static final String SAML_BINDING_HTTP_ARTIFACT =
- "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact";
- public static final String SAML_BINDING_HTTP_POST =
- "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST";
- public static final String SAML_BINDING_HTTP_REDIRECT =
- "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect";
- public static final String SAML_BINDING_SOAP = "urn:oasis:names:tc:SAML:2.0:bindings:SOAP";
- public static final String SAML_PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol";
- public static final String SAML_USAGE_SIGNING = "signing";
- private static final String SAML_CACHE_DURATION = "PT1H"; // one hour
-
- // Entity group for SAML clients.
- public static final String SECMGR_CLIENTS_ENTITIES_NAME = "security-manager-clients";
- public static final String SECMGR_CLIENTS_ENTITIES_COMMENT = "SAML client IdPs";
-
- // XML Digital Signature elements.
- private static QName dsName(String localPart) {
- return new QName(XMLSignature.XMLNS, localPart, "ds");
- }
-
- public static final QName XMLDSIG_KEY_INFO = dsName("KeyInfo");
- public static final QName XMLDSIG_X509_DATA = dsName("X509Data");
- public static final QName XMLDSIG_X509_CERTIFICATE = dsName("X509Certificate");
-
- // Entity for GSA.
- public static final String GSA_ENTITY_ID_ROOT = "http://google.com/enterprise/gsa/";
- public static final String GSA_ENTITY_COMMENT = "Description of the GSA";
- public static final String GSA_ENT_CONFIG_NAME_MARKER = "${ENT_CONFIG_NAME}";
-
- // Entity for security manager.
- public static final String SECMGR_ENTITY_ID_SUFFIX = "/security-manager";
- public static final String SECMGR_ENTITY_COMMENT = "Description of the Security Manager";
- static final String SECMGR_ID_FOR_ENTITY = "security-manager";
-
- // Google organization element.
- public static final String GOOGLE_ORGANIZATION_NAME = "google.com";
- public static final String GOOGLE_ORGANIZATION_DISPLAY_NAME = "Google Inc.";
- public static final String GOOGLE_ORGANIZATION_URL = "http://www.google.com/";
-
- // Endpoint URLs.
- private static final String HTTP_PROTOCOL = "http";
- private static final String HTTPS_PROTOCOL = "https";
- static final String GSA_HOST_MARKER = "$$GSA$$";
- private static final String SECMGR_WEBAPP_PATH = "/security-manager";
- private static final String LOCALHOST = "localhost";
-
- public static final String GSA_ASSERTION_CONSUMER_PATH = "SamlArtifactConsumer";
-
- public static final String SECMGR_SSO_PATH = "samlauthn";
- public static final String SECMGR_ARTIFACT_RESOLVER_PATH = "samlartifact";
- public static final String SECMGR_ASSERTION_CONSUMER_PATH = "samlassertionconsumer";
- public static final String SECMGR_AUTHZ_PATH = "samlauthz";
- public static final String X509_HEADER = "-----BEGIN CERTIFICATE-----";
- public static final String X509_FOOTER = "-----END CERTIFICATE-----";
-
- // Don't instantiate this class.
- private MetadataEditor() {}
-
- /**
- * A datatype to hold the parameters of a SAML client IdP.
- */
- @Immutable
- public static class SamlClientIdp {
-
- private final String id;
- private final String loginUrl;
- private final String artifactUrl;
- private final String certificate;
- private final String authzServiceUrl;
-
- private SamlClientIdp(String id, String loginUrl, String artifactUrl, String certificate,
- String authzServiceUrl) {
- Preconditions.checkNotNull(id);
- this.id = id;
- this.loginUrl = loginUrl;
- this.artifactUrl = artifactUrl;
- this.certificate = normalizeCertificate(certificate);
- this.authzServiceUrl = authzServiceUrl;
- }
-
- /**
- * Make a client with only IDP SSO components.
- *
- * @param id The entity ID for the IdP.
- * @param loginUrl The single sign-on service URL for the IdP.
- * @param artifactUrl The artifact resolution service URL for the IdP, or null if none.
- * @param certificate A PEM encoded X509 certificate, or null if none.
- * @return A new IDP SSO client.
- */
- public static SamlClientIdp makeSso(String id, String loginUrl, String artifactUrl,
- String certificate) {
- Preconditions.checkNotNull(loginUrl);
- Preconditions.checkArgument(artifactUrl != null ^ certificate != null);
- return new SamlClientIdp(id, loginUrl, artifactUrl, certificate, null);
- }
-
- /**
- * Make a client with only PDP components.
- *
- * @param id The entity ID for the PDP.
- * @param authzServiceUrl The URL for the PDP's AuthzService.
- * @return A new PDP client.
- */
- public static SamlClientIdp makePdp(String id, String authzServiceUrl) {
- Preconditions.checkNotNull(authzServiceUrl);
- return new SamlClientIdp(id, null, null, null, authzServiceUrl);
- }
-
- /**
- * @return True if this client has IdP SSO components.
- */
- public boolean hasSso() {
- return loginUrl != null && (artifactUrl != null || certificate != null);
- }
-
- /**
- * @return True if this client has PDP components.
- */
- public boolean hasPdp() {
- return authzServiceUrl != null;
- }
-
- /**
- * @return True if this client has components other than IDP SSO.
- */
- public boolean hasNonSso() {
- return hasPdp();
- }
-
- /**
- * @return True if this client has components other than PDP.
- */
- public boolean hasNonPdp() {
- return hasSso();
- }
-
- /**
- * Replace the IDP SSO components of this client with those of another.
- *
- * @param client The client to get the IDP SSO components from.
- * @return A copy of this client with its IDP SSO components replaced.
- */
- public SamlClientIdp replaceSso(SamlClientIdp client) {
- return new SamlClientIdp(id,
- client.getUrl(),
- client.getArtifactUrl(),
- client.getCertificate(),
- authzServiceUrl);
- }
-
- /**
- * @return A copy of this client with its IDP SSO components removed.
- */
- public SamlClientIdp removeSso() {
- return new SamlClientIdp(id, null, null, null, authzServiceUrl);
- }
-
- /**
- * Replace the PDP components of this client with those of another.
- *
- * @param client The client to get the PDP components from.
- * @return A copy of this client with its PDP components replaced.
- */
- public SamlClientIdp replacePdp(SamlClientIdp client) {
- return new SamlClientIdp(id,
- loginUrl,
- artifactUrl,
- certificate,
- client.getAuthzServiceUrl());
- }
-
- /**
- * @return A copy of this client with its PDP components removed.
- */
- public SamlClientIdp removePdp() {
- return new SamlClientIdp(id, loginUrl, artifactUrl, certificate, null);
- }
-
- /**
- * @return The entity ID of the SAML client.
- */
- public String getId() {
- return id;
- }
-
- /**
- * @return The single-sign-on entry URL for the SAML client.
- */
- public String getUrl() {
- return loginUrl;
- }
-
- /**
- * @return The artifact-resolution entry URL for the SAML client, or null if none.
- */
- public String getArtifactUrl() {
- return artifactUrl;
- }
-
- /**
- * @return The signing certificate for the SAML client, or null if none.
- */
- public String getCertificate() {
- return certificate;
- }
-
- /**
- * @return The AuthzService URL for the SAML client.
- */
- public String getAuthzServiceUrl() {
- return authzServiceUrl;
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(id, loginUrl, artifactUrl, certificate, authzServiceUrl);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == this) { return true; }
- if (!(obj instanceof SamlClientIdp)) { return false; }
- SamlClientIdp other = (SamlClientIdp) obj;
- return Objects.equal(id, other.id)
- && Objects.equal(loginUrl, other.loginUrl)
- && Objects.equal(artifactUrl, other.artifactUrl)
- && Objects.equal(certificate, other.certificate)
- && Objects.equal(authzServiceUrl, other.authzServiceUrl);
- }
- }
-
- /**
- * Get the SAML client IdPs from metadata.
- *
- * @param document The metadata as a {@link Document}.
- * @return A list of SAML client IdP descriptors.
- * @throws IllegalArgumentException if metadata can't be parsed.
- */
- public static List<SamlClientIdp> getSamlClientsInMetadata(Document document) {
- List<SamlClientIdp> clients = Lists.newArrayList();
- Set<String> idsSeen = Sets.newHashSet();
- Element entities = getSamlClients(document);
- if (entities != null) {
- NodeList nodes = getElementsByQname(entities, SAML_DESCRIPTOR_ENTITY);
- for (int index = 0; index < nodes.getLength(); index++) {
- Element element = Element.class.cast(nodes.item(index));
- SamlClientIdp client;
- try {
- client = parseClient(element, idsSeen);
- } catch (IllegalArgumentException e) {
- LOGGER.log(Level.WARNING, "Unable to parse SAML client spec: ", e);
- client = null;
- }
- if (client != null) {
- clients.add(client);
- }
- }
- }
- return clients;
- }
-
- private static SamlClientIdp parseClient(Element element, Set<String> idsSeen) {
- String id = element.getAttribute(SAML_ATTR_ENTITY_ID);
- Preconditions.checkArgument(!idsSeen.contains(id), "Duplicate entity ID in metadata: %s", id);
- idsSeen.add(id);
- SamlClientIdp sso = parseSso(id, findChildElement(element, SAML_DESCRIPTOR_IDP_SSO, false));
- SamlClientIdp pdp = parsePdp(id, findChildElement(element, SAML_DESCRIPTOR_PDP, false));
- return
- (sso == null) ? pdp
- : (pdp == null) ? sso
- : sso.replacePdp(pdp);
- }
-
- private static SamlClientIdp parseSso(String id, Element ssoRole) {
- if (ssoRole == null) {
- return null;
- }
- Element sso = findChildElement(ssoRole, SAML_SERVICE_SINGLE_SIGN_ON, true);
- Element ars = findChildElement(ssoRole, SAML_SERVICE_ARTIFACT_RESOLUTION, false);
- Element kd = findChildElement(ssoRole, SAML_DESCRIPTOR_KEY, false);
- return SamlClientIdp.makeSso(id,
- sso.getAttribute(SAML_ATTR_LOCATION),
- (ars == null) ? null : ars.getAttribute(SAML_ATTR_LOCATION),
- (kd == null) ? null : keyDescriptorCertificate(kd));
- }
-
- private static SamlClientIdp parsePdp(String id, Element pdp) {
- if (pdp == null) {
- return null;
- }
- Element authz = findChildElement(pdp, SAML_SERVICE_AUTHZ, true);
- return SamlClientIdp.makePdp(id,
- (authz == null) ? null : authz.getAttribute(SAML_ATTR_LOCATION));
- }
-
- /**
- * Set the SAML client IdPs in given metadata to the given set. Removes any
- * clients already in the metadata, then inserts the given clients.
- *
- * @param document The metadata as a {@link Document}. This document is
- * modified to contain the new clients.
- * @param clients A set of SAML client IdP descriptors; null means delete all.
- * @throws IOException if metadata can't be parsed or serialized.
- */
- public static void setSamlClientsInMetadata(Document document, Collection<SamlClientIdp> clients)
- throws IOException {
- if (clients == null) {
- deleteSamlClients(document);
- return;
- }
- Set<String> idsSeen = Sets.newHashSet();
- checkSamlClients(idsSeen, clients);
- deleteSamlClients(document);
- for (SamlClientIdp client : clients) {
- addIdpEntity(document, client);
- }
- }
-
- /**
- * Add the given SAML client IdPs to the given metadata.
- *
- * @param document The metadata as a {@link Document}. This document is
- * modified to contain the new clients.
- * @param clients A set of SAML client IdP descriptors; never null.
- * @throws IOException if metadata can't be parsed or serialized.
- */
- public static void addSamlClientsToMetadata(Document document, Collection<SamlClientIdp> clients)
- throws IOException {
- Set<String> idsSeen = Sets.newHashSet();
- for (SamlClientIdp client : getSamlClientsInMetadata(document)) {
- idsSeen.add(client.getId());
- }
- checkSamlClients(idsSeen, clients);
- for (SamlClientIdp client : clients) {
- addIdpEntity(document, client);
- }
- }
-
- private static void checkSamlClients(Set<String> idsSeen, Collection<SamlClientIdp> clients) {
- for (SamlClientIdp client : clients) {
- Preconditions.checkArgument(!idsSeen.contains(client.getId()),
- "Duplicate entity ID in clients: %s", client.getId());
- idsSeen.add(client.getId());
- }
- }
-
- /**
- * Find a SAML client with a given entity ID.
- *
- * @param entityId The entity ID to look for.
- * @param clients The clients to look through.
- * @return The client with that ID, or null if none.
- */
- public static SamlClientIdp findSamlClient(String entityId, Iterable<SamlClientIdp> clients) {
- for (SamlClientIdp client : clients) {
- if (entityId.equals(client.getId())) {
- return client;
- }
- }
- return null;
- }
-
- // **************** Versions of the above using XML strings ****************
-
- /**
- * Get the SAML client IdPs from metadata.
- *
- * @param metadata The metadata as XML String.
- * @return A list of SAML client IdP descriptors.
- * @throws IOException if metadata can't be parsed.
- */
- public static List<SamlClientIdp> getSamlClientsInMetadata(String metadata)
- throws IOException {
- return getSamlClientsInMetadata(stringToMetadataDocument(metadata));
- }
-
- /**
- * Set the SAML client IdPs in given metadata to the given set. Removes any
- * clients already in the metadata, then inserts the given clients.
- *
- * @param origMetadata The original metadata as an XML String.
- * @param clients The SAML client IdP descriptors; null means delete all.
- * @return The new metadata as XML String.
- * @throws IOException if metadata can't be parsed or serialized.
- */
- public static String setSamlClientsInMetadata(String origMetadata,
- Collection<SamlClientIdp> clients)
- throws IOException {
- Document document = stringToMetadataDocument(origMetadata);
- setSamlClientsInMetadata(document, clients);
- return metadataDocumentToString(document);
- }
-
- /**
- * Add the given SAML client IdPs to the given metadata.
- *
- * @param origMetadata The original metadata as an XML String.
- * @param clients The SAML client IdP descriptors; never null.
- * @return The new metadata as an XML String.
- * @throws IOException if metadata can't be parsed or serialized.
- */
- public static String addSamlClientsToMetadata(String origMetadata,
- Collection<SamlClientIdp> clients)
- throws IOException {
- Document document = stringToMetadataDocument(origMetadata);
- addSamlClientsToMetadata(document, clients);
- return metadataDocumentToString(document);
- }
-
- /**
- * Parse a metadata string into an XML document.
- *
- * @param metadata The metadata as an XML string.
- * @return The SAML metadata document.
- * @throws IOException if the metadata can't be parsed.
- */
- public static Document stringToMetadataDocument(String metadata)
- throws IOException {
- return readMetadataDocument(new StringReader(metadata));
- }
-
- /**
- * Convert a metadata XML document into a string.
- *
- * @param metadata The SAML metadata document.
- * @return The metadata as an XML string.
- * @throws IOException if the metadata can't be converted.
- */
- public static String metadataDocumentToString(Document metadata)
- throws IOException {
- return XmlUtil.getInstance().buildXmlString(metadata);
- }
-
- /**
- * Read SAML metadata and return it as a DOM document.
- *
- * @param input The Reader to read from.
- * @return The SAML metadata document.
- * @throws IOException if the document can't be parsed.
- */
- public static Document readMetadataDocument(Reader input)
- throws IOException {
- Document document = XmlUtil.getInstance().readXmlDocument(input);
- setConfigParams(document);
- return document;
- }
-
- /**
- * Write a SAML metadata document as XML.
- *
- * @param document The SAML metadata document to write.
- * @param writer The writer to write it to.
- * @throws IOException if the document can't be serialized.
- */
- public static void writeMetadataDocument(Document document, Writer writer)
- throws IOException {
- XmlUtil.getInstance().writeXmlDocument(document, writer);
- }
-
- /**
- * Read SAML metadata and return it as a DOM document.
- *
- * @param file The file to read from.
- * @return The SAML metadata document.
- * @throws IOException if the document can't be parsed.
- */
- public static Document readMetadataDocument(File file)
- throws IOException {
- Reader reader = new FileReader(file);
- try {
- return readMetadataDocument(reader);
- } finally {
- reader.close();
- }
- }
-
- /**
- * Write a SAML metadata document as XML.
- *
- * @param document The SAML metadata document to write.
- * @param file The file to write it to.
- * @throws IOException if the document can't be serialized.
- */
- public static void writeMetadataDocument(Document document, File file)
- throws IOException {
- Writer writer = new FileWriter(file);
- try {
- writeMetadataDocument(document, writer);
- } finally {
- writer.close();
- }
- }
-
- /**
- * Make a default metadata document for the security manager, when it is installed
- * onboard the GSA. This metadata uses the token "$$GSA$$" to represent the hostname of
- * the GSA; this token will be dynamically replaced with the real hostname on each
- * request. URLs that identify endpoints for connections between the GSA and the
- * security manager use "localhost".
- *
- * @return An XML document representing the metadata.
- */
- public static Document makeOnboardSecurityManagerMetadata() {
- Document document = XmlUtil.getInstance()
- .makeDocument(SAML_DESCRIPTOR_ENTITIES.getNamespaceURI(),
- SAML_DESCRIPTOR_ENTITIES.getLocalPart(),
- null);
- setConfigParams(document);
- Element entities = document.getDocumentElement();
- entities.setAttribute(SAML_ATTR_CACHE_DURATION, SAML_CACHE_DURATION);
- String gsaEntityId = GSA_ENTITY_ID_ROOT + GSA_ENT_CONFIG_NAME_MARKER;
- makeGsaEntity(entities, gsaEntityId);
- makeSmEntity(entities, gsaEntityId + SECMGR_ENTITY_ID_SUFFIX);
- return document;
- }
-
- /**
- * Make a SAML EntityDescriptor element for the GSA.
- *
- * @param entities The SAML EntitiesDescriptor element to put the element in.
- * @param id The SAML entity ID for the new element.
- * @return The EntityDescriptor as a DOM element.
- */
- private static Element makeGsaEntity(Element entities, String id) {
- Element entity = makeTopLevelEntity(entities, id, GSA_ENTITY_COMMENT);
-
- makeRole(entity, SAML_DESCRIPTOR_SP_SSO);
- makeAssertionConsumer(entity,
- SAML_BINDING_HTTP_ARTIFACT,
- makeGsaUrl(GSA_HOST_MARKER, GSA_ASSERTION_CONSUMER_PATH));
-
- makeGoogleOrganization(entity);
-
- return entity;
- }
-
- /**
- * Make a URL for the GSA.
- *
- * @param host The hostname to use.
- * @param path The URL path.
- * @return The URL as a string.
- */
- private static String makeGsaUrl(String host, String path) {
- URL url;
- try {
- url = new URL(HTTPS_PROTOCOL, host, -1, path);
- } catch (MalformedURLException e) {
- throw new IllegalStateException(e);
- }
- return url.toString();
- }
-
- /**
- * Make a SAML EntityDescriptor element for the security manager.
- *
- * @param entities The SAML EntitiesDescriptor element to put the new element in.
- * @param id The SAML entity ID for the new element.
- * @return The EntityDescriptor as a DOM element.
- */
- private static Element makeSmEntity(Element entities, String id) {
- Element entity = makeTopLevelEntity(entities, id, SECMGR_ENTITY_COMMENT);
- entity.setAttribute(XML_ATTR_ID, SECMGR_ID_FOR_ENTITY);
-
- makeRole(entity, SAML_DESCRIPTOR_IDP_SSO);
- makeSingleSignOn(entity, makeSecurityManagerUrl(GSA_HOST_MARKER, SECMGR_SSO_PATH));
- makeArtifactResolver(entity, makeSecurityManagerUrl(LOCALHOST, SECMGR_ARTIFACT_RESOLVER_PATH));
-
- makeRole(entity, SAML_DESCRIPTOR_SP_SSO);
- makeAssertionConsumer(entity,
- SAML_BINDING_HTTP_POST,
- makeSecurityManagerUrl(GSA_HOST_MARKER, SECMGR_ASSERTION_CONSUMER_PATH));
- makeAssertionConsumer(entity,
- SAML_BINDING_HTTP_ARTIFACT,
- makeSecurityManagerUrl(GSA_HOST_MARKER, SECMGR_ASSERTION_CONSUMER_PATH));
-
- makePdp(entity, makeSecurityManagerUrl(LOCALHOST, SECMGR_AUTHZ_PATH));
-
- makeGoogleOrganization(entity);
- return entity;
- }
-
- /**
- * Make a URL for a security manager servlet.
- *
- * @param host The hostname to use.
- * @param servletPath The part of the path that's specific to the servlet.
- * @return The URL as a string.
- */
- private static String makeSecurityManagerUrl(String host, String servletPath) {
- String path = SECMGR_WEBAPP_PATH + "/" + servletPath;
- URL url;
- try {
- if (LOCALHOST.equals(host)) {
- url = new URL(HTTP_PROTOCOL, host, path);
- } else {
- url = new URL(HTTPS_PROTOCOL, host, path);
- }
- } catch (MalformedURLException e) {
- throw new IllegalStateException(e);
- }
- return url.toString();
- }
-
- /**
- * Make a SAML Organization element for Google.
- *
- * @param entity The SAML Entity element to put the new element in.
- * @return The Organization as a DOM element.
- */
- private static Element makeGoogleOrganization(Element entity) {
- Element organization = makeElement(entity, SAML_ORGANIZATION);
- makeTextElementChild(organization, SAML_ORGANIZATION_NAME, GOOGLE_ORGANIZATION_NAME);
- makeTextElementChild(organization, SAML_ORGANIZATION_DISPLAY_NAME,
- GOOGLE_ORGANIZATION_DISPLAY_NAME);
- makeTextElementChild(organization, SAML_ORGANIZATION_URL, GOOGLE_ORGANIZATION_URL);
- return organization;
- }
-
- /**
- * Add an external SAML client IdP to a security manager metadata document. If there is
- * already an entity with the same ID, it is replaced.
- *
- * @param document A security manager metadata document.
- * @param client A SAML client IdP descriptor.
- */
- public static void addIdpEntity(Document document, SamlClientIdp client) {
- Element clients = getSamlClients(document);
- if (clients == null) {
- clients = makeSamlClients(document);
- }
- Element entity = makeEntity(clients, client.getId());
- if (client.hasSso()) {
- Element role = makeRole(entity, SAML_DESCRIPTOR_IDP_SSO);
- makeSingleSignOn(entity, client.getUrl());
- String artifactUrl = normalizeString(client.getArtifactUrl());
- if (artifactUrl != null) {
- makeArtifactResolver(entity, artifactUrl);
- }
- if (client.getCertificate() != null) {
- makeKeyDescriptor(role, client.getCertificate());
- }
- }
- if (client.hasPdp()) {
- makePdp(entity, client.getAuthzServiceUrl());
- }
- }
-
- private static String normalizeString(String s) {
- if (s == null) {
- return s;
- }
- s = s.trim();
- return s.isEmpty() ? null : s;
- }
-
- /**
- * Get the SAML EntitiesDescriptor that holds the client entities.
- *
- * @param document The SAML metadata document to look in.
- * @return The EntitiesDescriptor element, or null if no such.
- */
- public static Element getSamlClients(Document document) {
- NodeList nodes =
- getElementsByQname(document.getDocumentElement(), SAML_DESCRIPTOR_ENTITIES);
- for (int index = 0; index < nodes.getLength(); index++) {
- Element element = Element.class.cast(nodes.item(index));
- if (SECMGR_CLIENTS_ENTITIES_NAME.equals(element.getAttribute(SAML_ATTR_NAME))) {
- return element;
- }
- }
- return null;
- }
-
- /**
- * Make an empty SAML EntitiesDescriptor to hold client entities.
- *
- * @param document The SAML metadata document to look in.
- * @return The new EntitiesDescriptor as a DOM element.
- */
- private static Element makeSamlClients(Document document) {
- return makeTopLevelEntities(document.getDocumentElement(),
- SECMGR_CLIENTS_ENTITIES_NAME, SECMGR_CLIENTS_ENTITIES_COMMENT);
- }
-
- /**
- * Remove the SAML client entities descriptor, if there is one.
- *
- * @param document The SAML metadata document to look in.
- */
- private static void deleteSamlClients(Document document) {
- Element oldClients = getSamlClients(document);
- if (oldClients != null) {
- oldClients.getParentNode().removeChild(oldClients);
- }
- for (Comment comment :
- findChildComments(
- document.getDocumentElement(),
- SECMGR_CLIENTS_ENTITIES_COMMENT)) {
- comment.getParentNode().removeChild(comment);
- }
- }
-
-
- // Endpoint constructors.
-
- /**
- * Make a SAML SingleSignOn element.
- *
- * @param entity The SAML EntityDescriptor to put the new element in.
- * @param url The endpoint URL for the new element.
- * @return The new SingleSignOn as a DOM element.
- */
- private static Element makeSingleSignOn(Element entity, String url) {
- return makeEndpoint(findRole(entity, SAML_DESCRIPTOR_IDP_SSO),
- SAML_SERVICE_SINGLE_SIGN_ON, SAML_BINDING_HTTP_REDIRECT, url);
- }
-
- /**
- * Make a SAML ArtifactResolver element.
- *
- * @param entity The SAML EntityDescriptor to put the new element in.
- * @param url The endpoint URL for the new element.
- * @return The new ArtifactResolver as a DOM element.
- */
- private static Element makeArtifactResolver(Element entity, String url) {
- return makeIndexedEndpoint(findRole(entity, SAML_DESCRIPTOR_IDP_SSO),
- SAML_SERVICE_ARTIFACT_RESOLUTION, SAML_BINDING_SOAP, url);
- }
-
- /**
- * Make a SAML AssertionConsumer element.
- *
- * @param entity The SAML EntityDescriptor to put the new element in.
- * @param url The endpoint URL for the new element.
- * @return The new AssertionConsumer as a DOM element.
- */
- private static Element makeAssertionConsumer(Element entity, String binding, String url) {
- return makeIndexedEndpoint(findRole(entity, SAML_DESCRIPTOR_SP_SSO),
- SAML_SERVICE_ASSERTION_CONSUMER, binding, url);
- }
-
- /**
- * Make a SAML PDPDescriptor element.
- *
- * @param entity The SAML EntityDescriptor to put the new element in.
- * @param url The endpoint URL for the new element.
- * @return The new PDPDescriptor as a DOM element.
- */
- private static Element makePdp(Element entity, String url) {
- Element role = makeRole(entity, SAML_DESCRIPTOR_PDP);
- makeEndpoint(role, SAML_SERVICE_AUTHZ, SAML_BINDING_SOAP, url);
- return role;
- }
-
- /**
- * Find a role element with a given name.
- *
- * @param entity The SAML EntityDescriptor to look in.
- * @param qname The qname of the role element to look for.
- * @return The specified role element.
- * @throws IllegalArgumentException if there's no such child.
- */
- private static Element findRole(Element entity, QName qname) {
- return findChildElement(entity, qname, true);
- }
-
-
- // Element constructors.
-
- /**
- * Make a new top-level SAML EntitiesDescriptor element.
- *
- * @param entities The SAML EntitiesDescriptor to put the new element in.
- * @param name The name of the new element -- will be put in the name attribute.
- * @param comment A descriptive comment that will be added as an XML comment.
- * @return The new EntitiesDescriptor as a DOM element.
- */
- private static Element makeTopLevelEntities(Element entities, String name, String comment) {
- makeTextChild(entities, "\n");
- makeCommentChild(entities, " " + comment + " ");
- makeTextChild(entities, "\n");
- Element result = makeEntities(entities, name);
- makeTextChild(entities, "\n");
- return result;
- }
-
- /**
- * Make a new SAML EntitiesDescriptor element.
- *
- * @param entities The SAML EntitiesDescriptor to put the new element in.
- * @param name The name of the new element -- will be put in the name attribute.
- * @return The new EntitiesDescriptor as a DOM element.
- */
- private static Element makeEntities(Element entities, String name) {
- Element child = makeElementChild(entities, SAML_DESCRIPTOR_ENTITIES);
- child.setAttribute(SAML_ATTR_NAME, name);
- return child;
- }
-
- /**
- * Make a new top-level SAML EntityDescriptor element.
- *
- * @param entities The SAML EntitiesDescriptor to put the new element in.
- * @param id The id of the new element -- will be put in the ID attribute.
- * @param comment A descriptive comment that will be added as an XML comment.
- * @return The new EntityDescriptor as a DOM element.
- */
- private static Element makeTopLevelEntity(Element entities, String id, String comment) {
- makeTextChild(entities, "\n");
- makeCommentChild(entities, " " + comment + " ");
- makeTextChild(entities, "\n");
- Element entity = makeEntity(entities, id);
- makeTextChild(entities, "\n");
- return entity;
- }
-
- /**
- * Make a new SAML EntityDescriptor element.
- *
- * @param entities The SAML EntitiesDescriptor to put the new element in.
- * @param id The id of the new element -- will be put in the ID attribute.
- * @return The new EntityDescriptor as a DOM element.
- */
- private static Element makeEntity(Element entities, String id) {
- Element old = findEntity(entities, id);
- Element entity = makeElement(entities, SAML_DESCRIPTOR_ENTITY);
- entity.setAttribute(SAML_ATTR_ENTITY_ID, id);
- if (old == null) {
- entities.appendChild(entity);
- } else {
- entities.replaceChild(entity, old);
- }
- return entity;
- }
-
- /**
- * Find a SAML EntityDescriptor element.
- *
- * @param entities The SAML EntitiesDescriptor to look in.
- * @param id The id of the element to look for.
- * @return The specified EntityDescriptor, or null if no such.
- */
- private static Element findEntity(Element entities, String id) {
- NodeList nodes = getElementsByQname(entities, SAML_DESCRIPTOR_ENTITY);
- for (int index = 0; index < nodes.getLength(); index++) {
- Element element = Element.class.cast(nodes.item(index));
- if (id.equals(element.getAttribute(SAML_ATTR_ENTITY_ID))) {
- return element;
- }
- }
- return null;
- }
-
- /**
- * Make a new SAML role.
- *
- * @param entity the SAML EntityDescriptor to put the new role in.
- * @param qname The qname of the new role.
- * @return The new role as a DOM element.
- */
- private static Element makeRole(Element entity, QName qname) {
- Element role = makeElementChild(entity, qname);
- role.setAttribute(SAML_ATTR_PROTOCOL_SUPPORT_ENUMERATION, SAML_PROTOCOL);
- return role;
- }
-
- /**
- * Make a new SAML endpoint.
- *
- * @param role the SAML role to put the new endpoint in.
- * @param qname The qname of the new endpoint.
- * @param binding The SAML binding specifier.
- * @param url The endpoing URL.
- * @return The new endpoint as a DOM element.
- */
- private static Element makeEndpoint(Element role, QName qname, String binding, String url) {
- Element endpoint = makeElementChild(role, qname);
- endpoint.setAttribute(SAML_ATTR_BINDING, binding);
- endpoint.setAttribute(SAML_ATTR_LOCATION, url);
- return endpoint;
- }
-
- /**
- * Make a new SAML indexed endpoint.
- *
- * @param role the SAML role to put the new endpoint in.
- * @param qname The qname of the new endpoint.
- * @param binding The SAML binding specifier.
- * @param url The endpoing URL.
- * @return The new endpoint as a DOM element.
- */
- private static Element makeIndexedEndpoint(
- Element role, QName qname, String binding, String url) {
- int nChildren = countChildElements(role, qname);
- Element endpoint = makeEndpoint(role, qname, binding, url);
- endpoint.setAttribute(SAML_ATTR_INDEX, Integer.toString(nChildren));
- endpoint.setAttribute(SAML_ATTR_IS_DEFAULT, (nChildren == 0) ? "true" : "false");
- return endpoint;
- }
-
- /**
- * Make a new SAML key descriptor.
- *
- * @param role the SAML role to put the new descriptor in.
- * @param certificate The X509 certificate that the descriptor will contain.
- * @return The new key descriptor as a DOM element.
- */
- private static Element makeKeyDescriptor(Element role, String certificate) {
- Element keyDescriptor = makeElementChild(role, SAML_DESCRIPTOR_KEY);
- keyDescriptor.setAttribute(SAML_ATTR_USE, SAML_USAGE_SIGNING);
- Element keyInfo = makeElementChild(keyDescriptor, XMLDSIG_KEY_INFO);
- Element x509Data = makeElementChild(keyInfo, XMLDSIG_X509_DATA);
- makeTextElementChild(x509Data, XMLDSIG_X509_CERTIFICATE, normalizeCertificate(certificate));
- return keyDescriptor;
- }
-
- /**
- * Get the certificate out of a SAML key descriptor. Works only with key descriptors
- * created by #makeKeyDescriptor().
- *
- * @param keyDescriptor The SAML key descriptor to extract from.
- * @return The extracted certificate, or null if none such.
- */
- private static String keyDescriptorCertificate(Element keyDescriptor) {
- Element keyInfo = findChildElement(keyDescriptor, XMLDSIG_KEY_INFO, false);
- if (keyInfo == null) { return null; }
- Element x509Data = findChildElement(keyInfo, XMLDSIG_X509_DATA, false);
- if (x509Data == null) { return null; }
- Element x509Certificate = findChildElement(x509Data, XMLDSIG_X509_CERTIFICATE, false);
- if (x509Certificate == null) { return null; }
- NodeList nodes = x509Certificate.getChildNodes();
- if (nodes.getLength() == 1 && nodes.item(0).getNodeType() == Node.TEXT_NODE) {
- return normalizeCertificate(nodes.item(0).getNodeValue());
- }
- return null;
- }
-
- /**
- * Convert a PEM certificate to normalized form.
- *
- * @param s The certificate to normalize.
- * @return The normalized certificate.
- */
- public static String normalizeCertificate(String s) {
- if (s == null) {
- return s;
- }
- List<String> lines = Lists.newArrayList();
- for (String line : s.trim().split("\n+")) {
- lines.add(line.trim());
- }
- if (lines.size() == 0) {
- return null;
- }
- // Trim off X509 header/footer if present.
- if (X509_HEADER.equals(lines.get(0))
- && X509_FOOTER.equals(lines.get(lines.size() - 1))) {
- lines.remove(lines.size() - 1);
- lines.remove(0);
- }
- StringBuilder builder = new StringBuilder();
- for (String line : lines) {
- builder.append(line);
- builder.append("\n");
- }
- return builder.toString();
- }
-}
diff --git a/src/com/google/enterprise/secmgr/saml/OpenSamlUtil.java b/src/com/google/enterprise/secmgr/saml/OpenSamlUtil.java
index bb65627..6f822f2 100644
--- a/src/com/google/enterprise/secmgr/saml/OpenSamlUtil.java
+++ b/src/com/google/enterprise/secmgr/saml/OpenSamlUtil.java
@@ -16,14 +16,8 @@
import static org.opensaml.common.xml.SAMLConstants.SAML20P_NS;
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
-//import com.google.enterprise.secmgr.authncontroller.AuthnSession;
-import com.google.enterprise.secmgr.common.FileUtil;
-import com.google.enterprise.secmgr.common.HttpUtil;
-import com.google.enterprise.secmgr.config.ConfigSingleton;
-//import org.jdom.Namespace;
import org.joda.time.DateTime;
import org.opensaml.Configuration;
import org.opensaml.DefaultBootstrap;
@@ -37,9 +31,7 @@
import org.opensaml.common.binding.artifact.BasicSAMLArtifactMap;
import org.opensaml.common.binding.artifact.SAMLArtifactMap;
import org.opensaml.common.binding.artifact.SAMLArtifactMap.SAMLArtifactMapEntry;
-import org.opensaml.common.binding.security.SAMLProtocolMessageXMLSignatureSecurityPolicyRule;
import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
-import org.opensaml.saml2.binding.security.SAML2HTTPRedirectDeflateSignatureRule;
import org.opensaml.saml2.core.Action;
import org.opensaml.saml2.core.Artifact;
import org.opensaml.saml2.core.ArtifactResolve;
@@ -109,10 +101,7 @@
import org.opensaml.xml.security.keyinfo.provider.InlineX509DataProvider;
import org.opensaml.xml.security.keyinfo.provider.RSAKeyValueProvider;
import org.opensaml.xml.security.trust.TrustEngine;
-import org.opensaml.xml.security.x509.X509Credential;
import org.opensaml.xml.signature.KeyInfo;
-import org.opensaml.xml.signature.SignatureTrustEngine;
-import org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine;
import org.w3c.dom.Element;
import java.io.File;
@@ -120,15 +109,11 @@
import java.security.KeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
-import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable;
-import javax.servlet.http.HttpServletRequest;
import javax.xml.namespace.QName;
/**
@@ -927,31 +912,6 @@
}
/**
- * Run a message decoder.
- *
- * @param decoder The message decoder to run.
- * @param context The message context to pass to the decoder.
- * @param senderDescription A phrase describing the sender of the message.
- * @return True only if the message was successfully decode.
- */
- /*
- // Commented out to prevent pulling in AuthnSession.
- public static boolean runDecoder(MessageDecoder decoder, MessageContext context,
- AuthnSession session, String senderDescription) {
- try {
- decoder.decode(context);
- } catch (MessageDecodingException e) {
- LOGGER.warning(session.logMessage("Unable to decode SAML message from " + senderDescription));
- return false;
- } catch (SecurityException e) {
- LOGGER.warning(session.logMessage("Unable to verify signature of SAML message from " +
- senderDescription));
- return false;
- }
- return true;
- }*/
-
- /**
* Get a string for the current date/time, in the correct format for SAML.
*
* @return The corresponding string.
@@ -1024,50 +984,6 @@
return securityPolicy;
}
- /**
- * Get a signature policy rule for XML signatures, using metadata credentials.
- *
- * @param request An HTTP request to use for specializing the metadata.
- * @return An appropriate signature policy rule.
- * @throws IOException
- */
- public static synchronized SecurityPolicyRule getMetadataSignaturePolicyRule(
- HttpServletRequest request)
- throws IOException {
- return new SAMLProtocolMessageXMLSignatureSecurityPolicyRule(
- getMetadataSignatureTrustEngine(request));
- }
-
- /**
- * Get a signature policy rule for the redirect binding, using metadata credentials.
- *
- * @param request An HTTP request to use for specializing the metadata.
- * @return An appropriate signature policy rule.
- * @throws IOException
- */
- public static synchronized SecurityPolicyRule getMetadataSignaturePolicyRuleForRedirect(
- HttpServletRequest request)
- throws IOException {
- return new SAML2HTTPRedirectDeflateSignatureRule(
- getMetadataSignatureTrustEngine(request));
- }
-
- /**
- * Make a trust engine that checks signatures using credentials in metadata.
- *
- * @param request An HTTP request to use for specializing the metadata.
- * @return An appropriate signature trust engine.
- * @throws IOException
- */
- public static SignatureTrustEngine getMetadataSignatureTrustEngine(HttpServletRequest request)
- throws IOException {
- KeyInfoCredentialResolver keyInfoCredentialResolver = getStandardKeyInfoCredentialResolver();
- MetadataCredentialResolver credentialResolver =
- new MetadataCredentialResolver(getMetadata(request).getProvider());
- credentialResolver.setKeyInfoCredentialResolver(keyInfoCredentialResolver);
- return new ExplicitKeySignatureTrustEngine(credentialResolver, keyInfoCredentialResolver);
- }
-
private static KeyInfoCredentialResolver standardKeyInfoCredentialResolver = null;
/**
@@ -1123,40 +1039,6 @@
}
/**
- * Read a PEM-encoded X.509 certificate file and its associated private-key file and
- * return an {@link X509Credential} object.
- *
- * @param certFile The certificate file.
- * @param keyFile The private-key file.
- * @return The credential object, never null.
- * @throws IOException if there's some kind of error reading or converting the files.
- */
- public static X509Credential readX509Credential(File certFile, File keyFile)
- throws IOException {
- return SecurityHelper.getSimpleCredential(
- readX509CertificateFile(certFile),
- readPrivateKeyFile(keyFile));
- }
-
- /**
- * Read a PEM-encoded X.509 certificate file and return it as an {@link X509Certificate}
- * object.
- *
- * @param file The file to read.
- * @return The certificate object, never null.
- * @throws IOException if there's some kind of error reading or converting the file.
- */
- public static X509Certificate readX509CertificateFile(File file)
- throws IOException {
- String base64Cert = FileUtil.readPEMCertificateFile(file);
- try {
- return SecurityHelper.buildJavaX509Cert(base64Cert);
- } catch (CertificateException e) {
- throw new IOException(e);
- }
- }
-
- /**
* Read a PEM-encoded private-key file and return it as a {@link PrivateKey} object.
*
* @param file The file to read.
@@ -1206,87 +1088,4 @@
new MapBasedStorageService<String, SAMLArtifactMapEntry>(),
artifactLifetime);
}
-
- /**
- * Gets an entity descriptor with a given ID.
- *
- * @param id The ID of the entity to get.
- * @param request The servlet request to use for getting the metadata.
- * @return The entity's descriptor, or {@code null} if there's no entity with
- * that ID.
- */
- public static EntityDescriptor getEntity(String id, HttpServletRequest request)
- throws IOException {
- return getMetadata(request).getEntity(id);
- }
-
- /**
- * Gets the entity descriptor for the security manager.
- *
- * @param request The servlet request to use for getting the metadata.
- * @return The security manager's entity descriptor.
- */
- public static EntityDescriptor getSmEntity(HttpServletRequest request)
- throws IOException {
- return getMetadata(request).getSmEntity();
- }
-
- /**
- * Gets the entity ID for the security manager.
- *
- * @param request The servlet request to use for getting the metadata.
- * @return The security manager's entity ID.
- */
- public static String getSmEntityId(HttpServletRequest request)
- throws IOException {
- return getMetadata(request).getSmEntityId();
- }
-
- /**
- * Gets the SAML metadata.
- *
- * @param request The servlet request to use for customizing the metadata.
- * @return The metadata.
- */
- public static Metadata getMetadata(HttpServletRequest request)
- throws IOException {
- return Metadata.getInstance(HttpUtil.getRequestUrl(request, false));
- }
-
- @VisibleForTesting
- public static Metadata getMetadata()
- throws IOException {
- return Metadata.getInstance("localhost");
- }
-
- /**
- * Gets the credential to use for signing outgoing messages.
- *
- * @return The credential, or null if unable to obtain.
- */
- public static Credential getSigningCredential()
- throws IOException {
- String certFileName = ConfigSingleton.getSigningCertificateFilename();
- String keyFileName = ConfigSingleton.getSigningKeyFilename();
- if (certFileName == null || keyFileName == null) {
- LOGGER.info("No signing certificate available for outbound requests");
- return null;
- }
- File certFile = FileUtil.getContextFile(certFileName);
- File keyFile = FileUtil.getContextFile(keyFileName);
- if (!certFile.canRead()) {
- LOGGER.warning("Unable to read signing certificate file: " + certFile);
- return null;
- }
- if (!keyFile.canRead()) {
- LOGGER.warning("Unable to read signing key file: " + keyFile);
- return null;
- }
- try {
- return OpenSamlUtil.readX509Credential(certFile, keyFile);
- } catch (IOException e) {
- LOGGER.log(Level.WARNING, "Error reading certificate file(s): ", e);
- return null;
- }
- }
}
diff --git a/src/com/google/enterprise/secmgr/servlets/ResponseParser.java b/src/com/google/enterprise/secmgr/servlets/ResponseParser.java
index 3d82d21..93db806 100644
--- a/src/com/google/enterprise/secmgr/servlets/ResponseParser.java
+++ b/src/com/google/enterprise/secmgr/servlets/ResponseParser.java
@@ -21,7 +21,6 @@
import com.google.common.collect.Iterables;
import com.google.enterprise.secmgr.authncontroller.ExportedState;
import com.google.enterprise.secmgr.common.SecurityManagerUtil;
-import com.google.enterprise.secmgr.identity.Verification;
import com.google.enterprise.secmgr.modules.SamlClient;
import com.google.enterprise.secmgr.saml.OpenSamlUtil;
import com.google.enterprise.secmgr.saml.SamlLogUtil;
@@ -209,21 +208,6 @@
}
/**
- * Convert an assertion's expiration time to a form suitable for use in a
- * verification.
- *
- * @param time The given expiration time.
- * @return An expiration time usable by a verification.
- */
- public long expirationTimeToVerificationTime(DateTime time) {
- if (time != null) {
- return time.getMillis();
- }
- warn("SAML IdP failed to return expiration time");
- return Verification.NEVER_EXPIRES;
- }
-
- /**
* Gets an exported-state object. This information is a security manager
* extension. Must satisfy {@link #areAssertionsValid} prior to calling.
*/
diff --git a/src/com/google/inject/Inject.java b/src/com/google/inject/Inject.java
deleted file mode 100644
index 92da74e..0000000
--- a/src/com/google/inject/Inject.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// 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.google.inject;
-
-/**
- * Mock Inject.
- */
-public @interface Inject {}
diff --git a/src/com/google/inject/Injector.java b/src/com/google/inject/Injector.java
deleted file mode 100644
index 9495d19..0000000
--- a/src/com/google/inject/Injector.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// 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.google.inject;
-
-/**
- * Mock Injector.
- */
-public class Injector {
- public <T> T getInstance(Class<T> clazz) {
- throw new UnsupportedOperationException();
- }
-
- public <T> T getInstance(Key<T> key) {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/src/com/google/inject/Key.java b/src/com/google/inject/Key.java
deleted file mode 100644
index be051ff..0000000
--- a/src/com/google/inject/Key.java
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// 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.google.inject;
-
-/**
- * Mock Key.
- */
-public class Key<T> {
- public static <T> Key<T> get(TypeLiteral<T> type) {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/src/com/google/inject/Singleton.java b/src/com/google/inject/Singleton.java
deleted file mode 100644
index 0a998f5..0000000
--- a/src/com/google/inject/Singleton.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// 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.google.inject;
-
-/**
- * Mock Singleton.
- */
-public @interface Singleton {}
diff --git a/src/com/google/inject/TypeLiteral.java b/src/com/google/inject/TypeLiteral.java
deleted file mode 100644
index 326d6d7..0000000
--- a/src/com/google/inject/TypeLiteral.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// 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.google.inject;
-
-/**
- * Mock TypeLiteral.
- */
-public class TypeLiteral<T> {}
diff --git a/src/com/google/inject/name/Named.java b/src/com/google/inject/name/Named.java
deleted file mode 100644
index 41ea9b9..0000000
--- a/src/com/google/inject/name/Named.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// 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.google.inject.name;
-
-/**
- * Mock Named.
- */
-public @interface Named {
- String value();
-}
diff --git a/src/org/springframework/mock/web/MockHttpServletRequest.java b/src/org/springframework/mock/web/MockHttpServletRequest.java
deleted file mode 100644
index 1bef3a7..0000000
--- a/src/org/springframework/mock/web/MockHttpServletRequest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// 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 org.springframework.mock.web;
-
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * Mock of a mock
- */
-public interface MockHttpServletRequest extends HttpServletRequest {}
diff --git a/test/com/google/enterprise/adaptor/CronSchedulerTest.java b/test/com/google/enterprise/adaptor/CronSchedulerTest.java
index e0be115..68414a6 100644
--- a/test/com/google/enterprise/adaptor/CronSchedulerTest.java
+++ b/test/com/google/enterprise/adaptor/CronSchedulerTest.java
@@ -51,8 +51,10 @@
scheduler.schedule("0 0 1 1 1-7/2", noopRunnable).toString());
assertEquals("CronFuture([{0}, {0}, {1, 3, 5, 7, 9, 11}, {0}, {0}])",
scheduler.schedule("0 0 2-13/2 1 0", noopRunnable).toString());
- assertEquals("CronFuture([{0}, {0}, {0}, {0}, {0, 1, 2, 3, 4, 5, 6}])",
+ assertEquals("CronFuture([{0}, {0}, {0}, {0}, null])",
scheduler.schedule("0 0 1 1 *", noopRunnable).toString());
+ assertEquals("CronFuture([{0}, {0}, {0}, {0}, {0, 1, 2, 3, 4, 5, 6}])",
+ scheduler.schedule("0 0 1 1 */1", noopRunnable).toString());
}
@Test
@@ -152,46 +154,61 @@
// 1970-02-02T10:02:01Z, which is a Monday. That is 02:02:01 in PST.
timeProvider.time = 2800921L * 1000;
atomicCommand.get().run();
- Thread.sleep(10);
assertEquals(1, counter.get());
// Wrong minute.
// 1970-02-02T10:01:01Z, which is a Monday. That is 02:01:01 in PST.
timeProvider.time = 2800861L * 1000;
atomicCommand.get().run();
- Thread.sleep(10);
assertEquals(1, counter.get());
// Wrong hour.
// 1970-02-02T09:02:01Z, which is a Monday. That is 01:02:01 in PST.
timeProvider.time = 2797321L * 1000;
atomicCommand.get().run();
- Thread.sleep(10);
assertEquals(1, counter.get());
// Wrong day of month.
// 1970-02-02T10:02:01Z, which is a Monday. That is 02:02:01 in PST.
timeProvider.time = 2800921L * 1000;
- scheduler.reschedule(future, "2 2 1 2 2");
+ scheduler.reschedule(future, "2 2 1 2 *");
atomicCommand.get().run();
- Thread.sleep(10);
assertEquals(1, counter.get());
// Wrong month.
// 1970-02-02T10:02:01Z, which is a Monday. That is 02:02:01 in PST.
timeProvider.time = 2800921L * 1000;
- scheduler.reschedule(future, "2 2 2 1 2");
+ scheduler.reschedule(future, "2 2 2 1 1");
atomicCommand.get().run();
- Thread.sleep(10);
assertEquals(1, counter.get());
// Wrong day of week.
// 1970-02-02T10:02:01Z, which is a Monday. That is 02:02:01 in PST.
timeProvider.time = 2800921L * 1000;
+ scheduler.reschedule(future, "2 2 * 2 2");
+ atomicCommand.get().run();
+ assertEquals(1, counter.get());
+
+ // Wrong day of week and day of month.
+ // 1970-02-02T10:02:01Z, which is a Monday. That is 02:02:01 in PST.
+ timeProvider.time = 2800921L * 1000;
+ scheduler.reschedule(future, "2 2 1 2 2");
+ atomicCommand.get().run();
+ assertEquals(1, counter.get());
+
+ // Wrong day of week, but right day of month.
+ // 1970-02-02T10:02:01Z, which is a Monday. That is 02:02:01 in PST.
+ timeProvider.time = 2800921L * 1000;
scheduler.reschedule(future, "2 2 2 2 2");
atomicCommand.get().run();
- Thread.sleep(10);
- assertEquals(1, counter.get());
+ assertEquals(2, counter.get());
+
+ // Wrong day of month, but right day of week.
+ // 1970-02-02T10:02:01Z, which is a Monday. That is 02:02:01 in PST.
+ timeProvider.time = 2800921L * 1000;
+ scheduler.reschedule(future, "2 2 1 2 1");
+ atomicCommand.get().run();
+ assertEquals(3, counter.get());
}
@Test
diff --git a/test/com/google/enterprise/adaptor/HttpClientAdapterTest.java b/test/com/google/enterprise/adaptor/HttpClientAdapterTest.java
deleted file mode 100644
index 21db551..0000000
--- a/test/com/google/enterprise/adaptor/HttpClientAdapterTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// 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.google.enterprise.adaptor;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-import org.junit.rules.ExpectedException;
-
-/**
- * Test cases for {@link HttpClientAdapter}.
- */
-public class HttpClientAdapterTest {
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- private HttpClientAdapter httpClient = new HttpClientAdapter();
-
- @Test
- public void testHeadExchange() {
- thrown.expect(UnsupportedOperationException.class);
- httpClient.headExchange(null);
- }
-
- @Test
- public void testGetExchange() {
- thrown.expect(UnsupportedOperationException.class);
- httpClient.getExchange(null);
- }
-
- @Test
- public void testNewHttpExchange() {
- thrown.expect(UnsupportedOperationException.class);
- httpClient.newHttpExchange(null);
- }
-
- @Test
- public void testGetConnection() throws Exception {
- thrown.expect(UnsupportedOperationException.class);
- httpClient.getConnection(null);
- }
-
- @Test
- public void testHeadExchange2() {
- thrown.expect(UnsupportedOperationException.class);
- httpClient.headExchange(null, null);
- }
-
- @Test
- public void testGetExchange2() {
- thrown.expect(UnsupportedOperationException.class);
- httpClient.getExchange(null, null);
- }
-
- @Test
- public void testPostExchange3() {
- thrown.expect(UnsupportedOperationException.class);
- httpClient.postExchange(null, null, null);
- }
-
- @Test
- public void testNewHttpExchange2() {
- thrown.expect(UnsupportedOperationException.class);
- httpClient.newHttpExchange(null, null);
- }
-
- @Test
- public void testSetRequestTimeoutMillis() {
- thrown.expect(UnsupportedOperationException.class);
- httpClient.setRequestTimeoutMillis(-1);
- }
-}
diff --git a/test/com/google/enterprise/adaptor/MockHttpClient.java b/test/com/google/enterprise/adaptor/MockHttpClient.java
index ab3f35f..734f260 100644
--- a/test/com/google/enterprise/adaptor/MockHttpClient.java
+++ b/test/com/google/enterprise/adaptor/MockHttpClient.java
@@ -15,8 +15,6 @@
package com.google.enterprise.adaptor;
import com.google.common.collect.ListMultimap;
-import com.google.enterprise.secmgr.common.CookieStore;
-import com.google.enterprise.secmgr.common.GCookie;
import com.google.enterprise.secmgr.http.HttpClientInterface;
import com.google.enterprise.secmgr.http.HttpExchange;
@@ -36,16 +34,6 @@
protected abstract void handleExchange(ClientExchange ex);
@Override
- public HttpExchange headExchange(URL url) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public HttpExchange getExchange(URL url) {
- throw new UnsupportedOperationException();
- }
-
- @Override
public HttpExchange postExchange(URL url,
ListMultimap<String, String> parameters) {
HttpExchange exchange = new ClientExchange(url, "POST");
@@ -61,42 +49,6 @@
return exchange;
}
- @Override
- public HttpExchange newHttpExchange(URL url) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Connection getConnection(URL url) throws IOException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public HttpExchange headExchange(Connection connection, URL url) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public HttpExchange getExchange(Connection connection, URL url) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public HttpExchange postExchange(Connection connection, URL url,
- ListMultimap<String, String> parameters) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public HttpExchange newHttpExchange(Connection connection, URL url) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setRequestTimeoutMillis(int millisec) {
- throw new UnsupportedOperationException();
- }
-
/** Mocked exchange that calls {@link #handleExchange}. */
protected class ClientExchange implements HttpExchange {
private final URL url;
@@ -173,16 +125,6 @@
return requestHeaders.getFirst(headerName);
}
- @Override
- public void addCookies(Iterable<GCookie> cookies) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public CookieStore getCookies() {
- throw new UnsupportedOperationException();
- }
-
/** Does not copy provided byte array. */
@Override
public void setRequestBody(byte[] byteArrayRequestEntity) {
diff --git a/test/com/google/enterprise/adaptor/SamlIdentityProviderTest.java b/test/com/google/enterprise/adaptor/SamlIdentityProviderTest.java
index 8b67eba..56d0bcb 100644
--- a/test/com/google/enterprise/adaptor/SamlIdentityProviderTest.java
+++ b/test/com/google/enterprise/adaptor/SamlIdentityProviderTest.java
@@ -92,8 +92,11 @@
assertTrue(samlResponse.contains("https://entyo36.hot.corp.google.com/"
+ "security-manager/samlassertionconsumer"));
assertTrue(samlResponse.contains("user1"));
- assertTrue(samlResponse.contains("group1"));
- assertTrue(samlResponse.contains("group2"));
+ assertTrue(samlResponse.contains(
+ "<saml2:AttributeStatement><saml2:Attribute Name=\"member-of\">"
+ + "<saml2:AttributeValue>group1</saml2:AttributeValue>"
+ + "<saml2:AttributeValue>group2</saml2:AttributeValue>"
+ + "</saml2:Attribute></saml2:AttributeStatement>"));
}
@Test