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