View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.openr66.protocol.localhandler.packet;
21  
22  import io.netty.buffer.ByteBuf;
23  import io.netty.buffer.ByteBufAllocator;
24  import org.waarp.common.digest.FilesystemBasedDigest;
25  import org.waarp.common.logging.WaarpLogger;
26  import org.waarp.common.logging.WaarpLoggerFactory;
27  import org.waarp.common.utility.WaarpNettyUtil;
28  import org.waarp.common.utility.WaarpStringUtils;
29  import org.waarp.openr66.database.data.DbHostAuth;
30  import org.waarp.openr66.protocol.configuration.Configuration;
31  import org.waarp.openr66.protocol.configuration.PartnerConfiguration;
32  import org.waarp.openr66.protocol.exception.OpenR66ProtocolNoSslException;
33  import org.waarp.openr66.protocol.exception.OpenR66ProtocolPacketException;
34  import org.waarp.openr66.protocol.localhandler.LocalChannelReference;
35  import org.waarp.openr66.protocol.utils.R66Versions;
36  
37  /**
38   * Request Authentication class
39   * <p>
40   * header = "hostId" middle = "key bytes" end = localId + way + (optional
41   * version: could be a JSON on the form
42   * version.{})
43   */
44  public class AuthentPacket extends AbstractLocalPacket {
45    private static final WaarpLogger logger =
46        WaarpLoggerFactory.getLogger(AuthentPacket.class);
47  
48    private static final String NOT_ENOUGH_DATA = "Not enough data";
49  
50    private static final byte ASKVALIDATE = 0;
51  
52    private static final byte ANSWERVALIDATE = 1;
53  
54    private final Integer localId;
55  
56    private byte way;
57  
58    private String version;
59  
60    private String hostId;
61  
62    private byte[] key;
63  
64    /**
65     * @param headerLength
66     * @param middleLength
67     * @param endLength
68     * @param buf
69     *
70     * @return the new AuthentPacket from buffer
71     *
72     * @throws OpenR66ProtocolPacketException
73     */
74    public static AuthentPacket createFromBuffer(final int headerLength,
75                                                 final int middleLength,
76                                                 final int endLength,
77                                                 final ByteBuf buf)
78        throws OpenR66ProtocolPacketException {
79      if (headerLength - 1 <= 0) {
80        throw new OpenR66ProtocolPacketException(NOT_ENOUGH_DATA);
81      }
82      if (middleLength <= 0) {
83        throw new OpenR66ProtocolPacketException(NOT_ENOUGH_DATA);
84      }
85      if (endLength < 5) {
86        throw new OpenR66ProtocolPacketException(NOT_ENOUGH_DATA);
87      }
88      final byte[] bheader = new byte[headerLength - 1];
89      final byte[] bmiddle = new byte[middleLength];
90      buf.readBytes(bheader);
91      buf.readBytes(bmiddle);
92      // end part
93      final Integer newId = buf.readInt();
94      final byte valid = buf.readByte();
95      String version =
96          R66Versions.V2_4_12.getVersion(); // first base reference where it is unacceptable
97      if (endLength > 5) {
98        // version
99        final byte[] bversion = new byte[endLength - 5];
100       buf.readBytes(bversion);
101       version = new String(bversion, WaarpStringUtils.UTF8);
102     }
103     final String sheader = new String(bheader, WaarpStringUtils.UTF8);
104     return new AuthentPacket(sheader, bmiddle, newId, valid, version);
105   }
106 
107   /**
108    * @param hostId
109    * @param key
110    * @param newId
111    * @param valid
112    * @param version
113    */
114   private AuthentPacket(final String hostId, final byte[] key,
115                         final Integer newId, final byte valid,
116                         final String version) {
117     this.hostId = hostId;
118     this.key = key;
119     localId = newId;
120     way = valid;
121     Configuration.configuration.getVersions().put(hostId,
122                                                   new PartnerConfiguration(
123                                                       hostId, version));
124     logger.debug("Receive version {}", version);
125     this.version = version;
126   }
127 
128   /**
129    * @param hostId
130    * @param key
131    * @param newId
132    */
133   public AuthentPacket(final String hostId, final byte[] key,
134                        final Integer newId) {
135     this.hostId = hostId;
136     this.key = key;
137     localId = newId;
138     way = ASKVALIDATE;
139     if (!Configuration.configuration.getVersions().containsKey(hostId)) {
140       Configuration.configuration.getVersions().putIfAbsent(hostId,
141                                                             new PartnerConfiguration(
142                                                                 hostId));
143     }
144     version = Configuration.configuration.getVersions().get(hostId).toString();
145     logger.debug("Will send version {}", version);
146   }
147 
148   @Override
149   public final boolean hasGlobalBuffer() {
150     return true;
151   }
152 
153   @Override
154   public final synchronized void createAllBuffers(
155       final LocalChannelReference lcr, final int networkHeader)
156       throws OpenR66ProtocolPacketException {
157     if (hostId == null || key == null) {
158       throw new OpenR66ProtocolPacketException(NOT_ENOUGH_DATA);
159     }
160     final byte[] hostIdByte = hostId.getBytes(WaarpStringUtils.UTF8);
161     final int hostIdSize = hostIdByte.length;
162     final int keySize = key.length;
163     final byte[] bversion =
164         version != null? version.getBytes(WaarpStringUtils.UTF8) : null;
165     final int endSize = 5 + (version != null? bversion.length : 0);
166     final int globalSize =
167         networkHeader + hostIdSize + keySize + endSize + LOCAL_HEADER_SIZE;
168     int offset = networkHeader + LOCAL_HEADER_SIZE;
169     global = ByteBufAllocator.DEFAULT.ioBuffer(globalSize, globalSize);
170     header = WaarpNettyUtil.slice(global, offset, hostIdSize);
171     header.writeBytes(hostIdByte);
172     offset += hostIdSize;
173     middle = WaarpNettyUtil.slice(global, offset, keySize);
174     middle.writeBytes(key);
175     offset += keySize;
176     end = WaarpNettyUtil.slice(global, offset, endSize);
177     end.writeInt(localId);
178     end.writeByte(way);
179     if (version != null) {
180       end.writeBytes(bversion);
181     }
182   }
183 
184   @Override
185   public final byte getType() {
186     return LocalPacketFactory.AUTHENTPACKET;
187   }
188 
189   @Override
190   public final String toString() {
191     return "AuthentPacket: " + hostId + ' ' + localId + ' ' + way + ' ' +
192            version;
193   }
194 
195   /**
196    * @return the hostId
197    */
198   public final String getHostId() {
199     return hostId;
200   }
201 
202   /**
203    * @return the key
204    */
205   public final byte[] getKey() {
206     return key;
207   }
208 
209   /**
210    * @return the localId
211    */
212   public final Integer getLocalId() {
213     return localId;
214   }
215 
216   /**
217    * @return True if this packet is to be validated
218    */
219   public final boolean isToValidate() {
220     return way == ASKVALIDATE;
221   }
222 
223   /**
224    * Validate the connection
225    */
226   public final void validate(final boolean isSSL) {
227     way = ANSWERVALIDATE;
228     DbHostAuth auth = isSSL? Configuration.configuration.getHostSslAuth() :
229         Configuration.configuration.getHostAuth();
230     try {
231       hostId = Configuration.configuration.getHostId(isSSL);
232     } catch (final OpenR66ProtocolNoSslException e) {
233       hostId = Configuration.configuration.getHostId();
234       auth = Configuration.configuration.getHostAuth();
235     }
236     key = FilesystemBasedDigest.passwdCrypt(auth.getHostkey());
237     if (!Configuration.configuration.getVersions().containsKey(hostId)) {
238       Configuration.configuration.getVersions().putIfAbsent(hostId,
239                                                             new PartnerConfiguration(
240                                                                 hostId));
241     }
242     version = Configuration.configuration.getVersions().get(hostId).toString();
243     logger.debug("Validate version {}", version);
244     clear();
245   }
246 }