Skip to main content
summaryrefslogtreecommitdiffstats
blob: 5f819291a4810f1faba559dc802554d9cdfab9f3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/**
 * Copyright (c) 2004 - 2009 Eike Stepper (Berlin, Germany) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Eike Stepper - initial API and implementation
 */
package org.eclipse.net4j.util.security;

import org.eclipse.net4j.internal.util.bundle.OM;

import java.nio.ByteBuffer;
import java.util.Arrays;

/**
 * @author Eike Stepper
 */
public class ChallengeNegotiator extends ChallengeResponseNegotiator
{
  public static final int DEFAULT_TOKEN_LENGTH = 1024;

  private int tokenLength = DEFAULT_TOKEN_LENGTH;

  private IRandomizer randomizer;

  private IUserManager userManager;

  public ChallengeNegotiator()
  {
    super(true);
  }

  public int getTokenLength()
  {
    return tokenLength;
  }

  public void setTokenLength(int tokenLength)
  {
    this.tokenLength = tokenLength;
  }

  public IRandomizer getRandomizer()
  {
    return randomizer;
  }

  public void setRandomizer(IRandomizer randomizer)
  {
    this.randomizer = randomizer;
  }

  public IUserManager getUserManager()
  {
    return userManager;
  }

  public void setUserManager(IUserManager userManager)
  {
    this.userManager = userManager;
  }

  @Override
  protected void doBeforeActivate() throws Exception
  {
    super.doBeforeActivate();
    if (tokenLength <= 0)
    {
      throw new IllegalStateException("tokenLength must be positive");
    }

    if (randomizer == null)
    {
      throw new IllegalStateException("randomizer == null");
    }

    if (userManager == null)
    {
      throw new IllegalStateException("userManager == null");
    }
  }

  protected byte[] createRandomToken()
  {
    byte[] token = new byte[tokenLength];
    randomizer.nextBytes(token);
    return token;
  }

  protected byte[] encryptToken(String userID, byte[] token) throws NegotiationException
  {
    try
    {
      return userManager.encrypt(userID, token, getEncryptionAlgorithmName(), getEncryptionSaltBytes(),
          getEncryptionIterationCount());
    }
    catch (Exception ex)
    {
      OM.LOG.error("Token encryption failed", ex);
      return null;
    }
  }

  @Override
  protected void createChallenge(INegotiationContext context, ByteBuffer challenge)
  {
    // Create and remember a random token
    byte[] randomToken = createRandomToken();
    context.setInfo(randomToken);

    // Set the token into challenge
    challenge.putInt(randomToken.length);
    challenge.put(randomToken);
  }

  @Override
  protected boolean handleResponse(INegotiationContext context, ByteBuffer response)
  {
    // Get remembered random token
    byte[] randomToken = (byte[])context.getInfo();

    // Get userID from response
    int size = response.getInt();
    byte[] userIDBytes = new byte[size];
    response.get(userIDBytes);
    String userID = new String(userIDBytes);

    // Get crypted token from response
    size = response.getInt();
    byte[] responseToken = new byte[size];
    response.get(responseToken);

    // Encrypt the remembered token and compare to crypted token from response
    byte[] cryptedToken = encryptToken(userID, randomToken);
    boolean success = Arrays.equals(responseToken, cryptedToken);
    if (success)
    {
      context.setUserID(userID);
    }

    return success;
  }
}

Back to the top