Remove use of yangtools.concepts.Builder
[netconf.git] / netconf / callhome-protocol / src / main / java / org / opendaylight / netconf / callhome / protocol / CallHomeAuthorization.java
1 /*
2  * Copyright (c) 2016 Brocade Communication Systems and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netconf.callhome.protocol;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.collect.ImmutableSet;
13 import java.security.KeyPair;
14 import java.util.Collection;
15 import java.util.HashSet;
16 import java.util.Set;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.opendaylight.netconf.shaded.sshd.client.session.ClientSession;
19
20 /**
21  * Authorization context for incoming call home sessions.
22  *
23  * @see CallHomeAuthorizationProvider
24  */
25 public abstract class CallHomeAuthorization {
26     private static final CallHomeAuthorization REJECTED = new CallHomeAuthorization() {
27
28         @Override
29         public boolean isServerAllowed() {
30             return false;
31         }
32
33         @Override
34         protected String getSessionName() {
35             return "";
36         }
37
38         @Override
39         protected void applyTo(final ClientSession session) {
40             throw new IllegalStateException("Server is not allowed.");
41         }
42     };
43
44     /**
45      * Returns CallHomeAuthorization object with intent to
46      * reject incoming connection.
47      *
48      * <p>
49      * {@link CallHomeAuthorizationProvider} may use returned object
50      * as return value for
51      * {@link CallHomeAuthorizationProvider#provideAuth(java.net.SocketAddress, java.security.PublicKey)}
52      * if the incoming session should be rejected due to policy implemented
53      * by provider.
54      *
55      * @return CallHomeAuthorization with {@code isServerAllowed() == false}
56      */
57     public static final CallHomeAuthorization rejected() {
58         return REJECTED;
59     }
60
61     /**
62      * Creates a builder for CallHomeAuthorization with intent
63      * to accept incoming connection and to provide credentials.
64      *
65      * <p>
66      * Note: If session with same sessionName is already opened and
67      * active, incoming session will be rejected.
68      *
69      * @param sessionName Application specific unique identifier for incoming session
70      * @param username    Username to be used for authorization
71      * @return Builder which allows to specify credentials.
72      */
73     public static final Builder serverAccepted(final String sessionName, final String username) {
74         return new Builder(sessionName, username);
75     }
76
77     /**
78      * Returns true if incomming connection is allowed.
79      *
80      * @return true if incoming connection from SSH Server is allowed.
81      */
82     public abstract boolean isServerAllowed();
83
84     /**
85      * Applies provided authentification to Mina SSH Client Session.
86      *
87      * @param session Client Session to which authorization parameters will by applied
88      */
89     protected abstract void applyTo(ClientSession session);
90
91     protected abstract String getSessionName();
92
93     /**
94      * Builder for CallHomeAuthorization which accepts incoming connection.
95      *
96      * <p>
97      * Use {@link CallHomeAuthorization#serverAccepted(String, String)} to instantiate builder.
98      */
99     public static class Builder {
100         private final String nodeId;
101         private final String username;
102         private final Set<String> passwords = new HashSet<>();
103         private final Set<KeyPair> clientKeys = new HashSet<>();
104
105         Builder(final String nodeId, final String username) {
106             this.nodeId = requireNonNull(nodeId);
107             this.username = requireNonNull(username);
108         }
109
110         /**
111          * Adds password, which will be used for password-based authorization.
112          *
113          * @param password Password to be used for password-based authorization.
114          * @return this builder.
115          */
116         public Builder addPassword(final String password) {
117             passwords.add(password);
118             return this;
119         }
120
121         /**
122          * Adds public / private key pair to be used for public-key based authorization.
123          *
124          * @param clientKey Keys to be used for authorization.
125          * @return this builder.
126          */
127         public Builder addClientKeys(final KeyPair clientKey) {
128             clientKeys.add(clientKey);
129             return this;
130         }
131
132         public @NonNull CallHomeAuthorization build() {
133             return new ServerAllowed(nodeId, username, passwords, clientKeys);
134         }
135     }
136
137     private static final class ServerAllowed extends CallHomeAuthorization {
138         private final String nodeId;
139         private final String username;
140         private final Set<String> passwords;
141         private final Set<KeyPair> clientKeyPair;
142
143         ServerAllowed(final String nodeId, final String username, final Collection<String> passwords,
144                       final Collection<KeyPair> clientKeyPairs) {
145             this.username = requireNonNull(username);
146             this.passwords = ImmutableSet.copyOf(passwords);
147             clientKeyPair = ImmutableSet.copyOf(clientKeyPairs);
148             this.nodeId = requireNonNull(nodeId);
149         }
150
151         @Override
152         protected String getSessionName() {
153             return nodeId;
154         }
155
156         @Override
157         public boolean isServerAllowed() {
158             return true;
159         }
160
161         @Override
162         protected void applyTo(final ClientSession session) {
163             session.setUsername(username);
164
165             // First try authentication using server host keys, else try password.
166             for (KeyPair keyPair : clientKeyPair) {
167                 session.addPublicKeyIdentity(keyPair);
168             }
169             for (String password : passwords) {
170                 session.addPasswordIdentity(password);
171             }
172         }
173     }
174 }