001: /*
002: * Copyright 2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.ws.soap.security.xwss.callback;
018:
019: import java.text.ParseException;
020: import java.text.SimpleDateFormat;
021: import java.util.Calendar;
022: import java.util.Date;
023: import java.util.GregorianCalendar;
024:
025: import com.sun.xml.wss.impl.callback.TimestampValidationCallback;
026:
027: /**
028: * A default implementation of a <code>TimestampValidationCallback.TimestampValidator</code>. Based on a version found
029: * in the JWSDP samples.
030: *
031: * @author Arjen Poutsma
032: */
033: public class DefaultTimestampValidator implements
034: TimestampValidationCallback.TimestampValidator {
035:
036: public void validate(TimestampValidationCallback.Request request)
037: throws TimestampValidationCallback.TimestampValidationException {
038: if (request instanceof TimestampValidationCallback.UTCTimestampRequest) {
039: TimestampValidationCallback.UTCTimestampRequest utcRequest = (TimestampValidationCallback.UTCTimestampRequest) request;
040: Date created = parseDate(utcRequest.getCreated());
041:
042: validateCreationTime(created, utcRequest.getMaxClockSkew(),
043: utcRequest.getTimestampFreshnessLimit());
044:
045: if (utcRequest.getExpired() != null) {
046: Date expired = parseDate(utcRequest.getExpired());
047: validateExpirationTime(expired, utcRequest
048: .getMaxClockSkew());
049: }
050: } else {
051: throw new TimestampValidationCallback.TimestampValidationException(
052: "Unsupport request: [" + request + "]");
053: }
054: }
055:
056: private Date getFreshnessAndSkewAdjustedDate(long maxClockSkew,
057: long timestampFreshnessLimit) {
058: Calendar c = new GregorianCalendar();
059: long offset = c.get(Calendar.ZONE_OFFSET);
060: if (c.getTimeZone().inDaylightTime(c.getTime())) {
061: offset += c.getTimeZone().getDSTSavings();
062: }
063: long beforeTime = c.getTimeInMillis();
064: long currentTime = beforeTime - offset;
065:
066: long adjustedTime = currentTime - maxClockSkew
067: - timestampFreshnessLimit;
068: c.setTimeInMillis(adjustedTime);
069:
070: return c.getTime();
071: }
072:
073: private Date getGMTDateWithSkewAdjusted(Calendar calendar,
074: long maxClockSkew, boolean addSkew) {
075: long offset = calendar.get(Calendar.ZONE_OFFSET);
076: if (calendar.getTimeZone().inDaylightTime(calendar.getTime())) {
077: offset += calendar.getTimeZone().getDSTSavings();
078: }
079: long beforeTime = calendar.getTimeInMillis();
080: long currentTime = beforeTime - offset;
081:
082: if (addSkew) {
083: currentTime = currentTime + maxClockSkew;
084: } else {
085: currentTime = currentTime - maxClockSkew;
086: }
087:
088: calendar.setTimeInMillis(currentTime);
089: return calendar.getTime();
090: }
091:
092: private Date parseDate(String date)
093: throws TimestampValidationCallback.TimestampValidationException {
094: SimpleDateFormat calendarFormatter1 = new SimpleDateFormat(
095: "yyyy-MM-dd'T'HH:mm:ss'Z'");
096: SimpleDateFormat calendarFormatter2 = new SimpleDateFormat(
097: "yyyy-MM-dd'T'HH:mm:ss'.'SSS'Z'");
098:
099: try {
100: try {
101: return calendarFormatter1.parse(date);
102: } catch (ParseException ignored) {
103: return calendarFormatter2.parse(date);
104: }
105: } catch (ParseException ex) {
106: throw new TimestampValidationCallback.TimestampValidationException(
107: "Could not parse request date: " + date, ex);
108: }
109: }
110:
111: private void validateCreationTime(Date created, long maxClockSkew,
112: long timestampFreshnessLimit)
113: throws TimestampValidationCallback.TimestampValidationException {
114: Date current = getFreshnessAndSkewAdjustedDate(maxClockSkew,
115: timestampFreshnessLimit);
116:
117: if (created.before(current)) {
118: throw new TimestampValidationCallback.TimestampValidationException(
119: "The creation time is older than currenttime - timestamp-freshness-limit - max-clock-skew");
120: }
121:
122: Date currentTime = getGMTDateWithSkewAdjusted(
123: new GregorianCalendar(), maxClockSkew, true);
124: if (currentTime.before(created)) {
125: throw new TimestampValidationCallback.TimestampValidationException(
126: "The creation time is ahead of the current time.");
127: }
128: }
129:
130: private void validateExpirationTime(Date expires, long maxClockSkew)
131: throws TimestampValidationCallback.TimestampValidationException {
132: Date currentTime = getGMTDateWithSkewAdjusted(
133: new GregorianCalendar(), maxClockSkew, false);
134: if (expires.before(currentTime)) {
135: throw new TimestampValidationCallback.TimestampValidationException(
136: "The current time is ahead of the expiration time in Timestamp");
137: }
138: }
139:
140: }
|