1 package com.atlassian.seraph.cookie;
2
3 import com.atlassian.seraph.config.SecurityConfigFactory;
4 import com.atlassian.seraph.util.EncryptionUtils;
5 import org.apache.log4j.Logger;
6
7 import java.net.URLEncoder;
8 import java.net.URLDecoder;
9 import java.io.UnsupportedEncodingException;
10
11
12
13
14
15
16 public class EncryptedCookieEncoder implements CookieEncoder
17 {
18 private static final Logger LOG = Logger.getLogger(EncryptedCookieEncoder.class);
19
20 private static final String URL_ENCODING = "UTF-8";
21
22 private static final String SEPARATOR = "^^^";
23
24 private final EncryptionUtils encryptionUtils;
25
26 public EncryptedCookieEncoder()
27 {
28 this(SecurityConfigFactory.getInstance().getCookieEncoding());
29 }
30
31 protected EncryptedCookieEncoder(final String password)
32 {
33 if ((password == null) || (password.length() == 0))
34 {
35 throw new IllegalArgumentException("The password must be specified");
36 }
37 encryptionUtils = new EncryptionUtils();
38 encryptionUtils.setPassword(password);
39 }
40
41 public String encodePasswordCookie(final String username, final String password, final String encoding)
42 {
43 final StringBuffer sb = new StringBuffer();
44 sb.append(username).append(EncryptedCookieEncoder.SEPARATOR).append(password);
45 return escapeInvalidCookieCharacters(encryptionUtils.encrypt(sb.toString()));
46 }
47
48 public String[] decodePasswordCookie(final String cookieVal, final String encoding)
49 {
50 final String[] result = new String[2];
51 try
52 {
53 final String text = encryptionUtils.decrypt(unescapeInvalidCookieCharacters(cookieVal));
54 final int pos = text.indexOf(EncryptedCookieEncoder.SEPARATOR);
55 if (pos < 0)
56 {
57 EncryptedCookieEncoder.LOG.info("Successfully decrypted password cookie, but decrypted value '" + text + "' is invalid because separator ('" + EncryptedCookieEncoder.SEPARATOR + "') was not found. Returning null.");
58 return null;
59 }
60 result[0] = text.substring(0, pos);
61 result[1] = text.substring(pos + EncryptedCookieEncoder.SEPARATOR.length());
62 }
63 catch (final RuntimeException ex)
64 {
65 EncryptedCookieEncoder.LOG.info("Password cookie could not be decrypted, trying old insecure method of decoding it");
66 return new InsecureCookieEncoder().decodePasswordCookie(cookieVal, encoding);
67 }
68 return result;
69 }
70
71
72
73
74
75
76
77
78
79 private static String escapeInvalidCookieCharacters(final String s)
80 {
81 try
82 {
83 return URLEncoder.encode(s, EncryptedCookieEncoder.URL_ENCODING);
84 }
85 catch (final UnsupportedEncodingException e)
86 {
87 throw new AssertionError(e);
88 }
89 }
90
91
92
93
94
95
96
97
98
99 private static String unescapeInvalidCookieCharacters(final String s)
100 {
101 try
102 {
103 return URLDecoder.decode(s, EncryptedCookieEncoder.URL_ENCODING);
104 }
105 catch (final UnsupportedEncodingException e)
106 {
107 EncryptedCookieEncoder.LOG.fatal("UTF-8 encoding unsupported !!?!! How is that possible?", e);
108 throw new RuntimeException(e);
109 }
110 }
111 }