Do not require NetconfSessionImpl
[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.apache.sshd.client.session.ClientSession;
18
19 /**
20  * Authorization context for incoming call home sessions.
21  *
22  * @see CallHomeAuthorizationProvider
23  */
24 public abstract class CallHomeAuthorization {
25     private static final CallHomeAuthorization REJECTED = new CallHomeAuthorization() {
26
27         @Override
28         public boolean isServerAllowed() {
29             return false;
30         }
31
32         @Override
33         protected String getSessionName() {
34             return "";
35         }
36
37         @Override
38         protected void applyTo(final ClientSession session) {
39             throw new IllegalStateException("Server is not allowed.");
40         }
41     };
42
43     /**
44      * Returns CallHomeAuthorization object with intent to
45      * reject incoming connection.
46      *
47      * <p>
48      * {@link CallHomeAuthorizationProvider} may use returned object
49      * as return value for
50      * {@link CallHomeAuthorizationProvider#provideAuth(java.net.SocketAddress, java.security.PublicKey)}
51      * if the incoming session should be rejected due to policy implemented
52      * by provider.
53      *
54      * @return CallHomeAuthorization with {@code isServerAllowed() == false}
55      */
56     public static final CallHomeAuthorization rejected() {
57         return REJECTED;
58     }
59
60     /**
61      * Creates a builder for CallHomeAuthorization with intent
62      * to accept incoming connection and to provide credentials.
63      *
64      * <p>
65      * Note: If session with same sessionName is already opened and
66      * active, incoming session will be rejected.
67      *
68      * @param sessionName Application specific unique identifier for incoming session
69      * @param username    Username to be used for authorization
70      * @return Builder which allows to specify credentials.
71      */
72     public static final Builder serverAccepted(final String sessionName, final String username) {
73         return new Builder(sessionName, username);
74     }
75
76     /**
77      * Returns true if incomming connection is allowed.
78      *
79      * @return true if incoming connection from SSH Server is allowed.
80      */
81     public abstract boolean isServerAllowed();
82
83     /**
84      * Applies provided authentification to Mina SSH Client Session.
85      *
86      * @param session Client Session to which authorization parameters will by applied
87      */
88     protected abstract void applyTo(ClientSession session);
89
90     protected abstract String getSessionName();
91
92     /**
93      * Builder for CallHomeAuthorization which accepts incoming connection.
94      *
95      * <p>
96      * Use {@link CallHomeAuthorization#serverAccepted(String, String)} to instantiate
97      * builder.
98      */
99     public static class Builder implements org.opendaylight.yangtools.concepts.Builder<CallHomeAuthorization> {
100
101         private final String nodeId;
102         private final String username;
103         private final Set<String> passwords = new HashSet<>();
104         private final Set<KeyPair> clientKeys = new HashSet<>();
105
106         Builder(final String nodeId, final String username) {
107             this.nodeId = requireNonNull(nodeId);
108             this.username = requireNonNull(username);
109         }
110
111         /**
112          * Adds password, which will be used for password-based authorization.
113          *
114          * @param password Password to be used for password-based authorization.
115          * @return this builder.
116          */
117         public Builder addPassword(final String password) {
118             this.passwords.add(password);
119             return this;
120         }
121
122         /**
123          * Adds public / private key pair to be used for public-key based authorization.
124          *
125          * @param clientKey Keys to be used for authorization.
126          * @return this builder.
127          */
128         public Builder addClientKeys(final KeyPair clientKey) {
129             this.clientKeys.add(clientKey);
130             return this;
131         }
132
133         @Override
134         public CallHomeAuthorization build() {
135             return new ServerAllowed(nodeId, username, passwords, clientKeys);
136         }
137
138     }
139
140     private static class ServerAllowed extends CallHomeAuthorization {
141
142         private final String nodeId;
143         private final String username;
144         private final Set<String> passwords;
145         private final Set<KeyPair> clientKeyPair;
146
147         ServerAllowed(final String nodeId, final String username, final Collection<String> passwords,
148                       final Collection<KeyPair> clientKeyPairs) {
149             this.username = requireNonNull(username);
150             this.passwords = ImmutableSet.copyOf(passwords);
151             this.clientKeyPair = ImmutableSet.copyOf(clientKeyPairs);
152             this.nodeId = requireNonNull(nodeId);
153         }
154
155         @Override
156         protected String getSessionName() {
157             return nodeId;
158         }
159
160         @Override
161         public boolean isServerAllowed() {
162             return true;
163         }
164
165         @Override
166         protected void applyTo(final ClientSession session) {
167             session.setUsername(username);
168
169             // First try authentication using server host keys, else try password.
170             for (KeyPair keyPair : clientKeyPair) {
171                 session.addPublicKeyIdentity(keyPair);
172             }
173             for (String password : passwords) {
174                 session.addPasswordIdentity(password);
175             }
176         }
177     }
178 }