1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.javax.security.sasl;
19
20import java.security.Provider;
21import java.security.Security;
22import org.apache.harmony.javax.security.auth.callback.CallbackHandler;
23
24
25
26import java.util.Collection;
27import java.util.Collections;
28import java.util.Enumeration;
29import java.util.Map;
30import java.util.HashSet;
31import java.util.Iterator;
32
33public class Sasl {
34    // SaslClientFactory service name
35    private static final String CLIENTFACTORYSRV = "SaslClientFactory"; //$NON-NLS-1$
36
37    // SaslServerFactory service name
38    private static final String SERVERFACTORYSRV = "SaslServerFactory"; //$NON-NLS-1$
39
40    public static final String POLICY_NOPLAINTEXT = "javax.security.sasl.policy.noplaintext"; //$NON-NLS-1$
41
42    public static final String POLICY_NOACTIVE = "javax.security.sasl.policy.noactive"; //$NON-NLS-1$
43
44    public static final String POLICY_NODICTIONARY = "javax.security.sasl.policy.nodictionary"; //$NON-NLS-1$
45
46    public static final String POLICY_NOANONYMOUS = "javax.security.sasl.policy.noanonymous"; //$NON-NLS-1$
47
48    public static final String POLICY_FORWARD_SECRECY = "javax.security.sasl.policy.forward"; //$NON-NLS-1$
49
50    public static final String POLICY_PASS_CREDENTIALS = "javax.security.sasl.policy.credentials"; //$NON-NLS-1$
51
52    public static final String MAX_BUFFER = "javax.security.sasl.maxbuffer"; //$NON-NLS-1$
53
54    public static final String RAW_SEND_SIZE = "javax.security.sasl.rawsendsize"; //$NON-NLS-1$
55
56    public static final String REUSE = "javax.security.sasl.reuse"; //$NON-NLS-1$
57
58    public static final String QOP = "javax.security.sasl.qop"; //$NON-NLS-1$
59
60    public static final String STRENGTH = "javax.security.sasl.strength"; //$NON-NLS-1$
61
62    public static final String SERVER_AUTH = "javax.security.sasl.server.authentication"; //$NON-NLS-1$
63
64    // Default public constructor is overridden
65    private Sasl() {
66        super();
67    }
68
69    // Forms new instance of factory
70    private static Object newInstance(String factoryName, Provider prv) throws SaslException {
71        String msg = "auth.31"; //$NON-NLS-1$
72        Object factory;
73        ClassLoader cl = prv.getClass().getClassLoader();
74        if (cl == null) {
75            cl = ClassLoader.getSystemClassLoader();
76        }
77        try {
78            factory = (Class.forName(factoryName, true, cl)).newInstance();
79            return factory;
80        } catch (IllegalAccessException e) {
81            throw new SaslException(msg + factoryName, e);
82        } catch (ClassNotFoundException e) {
83            throw new SaslException(msg + factoryName, e);
84        } catch (InstantiationException e) {
85            throw new SaslException(msg + factoryName, e);
86        }
87    }
88
89    /**
90     * This method forms the list of SaslClient/SaslServer factories which are
91     * implemented in used providers
92     */
93    private static Collection<?> findFactories(String service) {
94        HashSet<Object> fact = new HashSet<Object>();
95        Provider[] pp = Security.getProviders();
96        if ((pp == null) || (pp.length == 0)) {
97            return fact;
98        }
99        HashSet<String> props = new HashSet<String>();
100        for (int i = 0; i < pp.length; i++) {
101            String prName = pp[i].getName();
102            Enumeration<Object> keys = pp[i].keys();
103            while (keys.hasMoreElements()) {
104                String s = (String) keys.nextElement();
105                if (s.startsWith(service)) {
106                    String prop = pp[i].getProperty(s);
107                    try {
108                        if (props.add(prName.concat(prop))) {
109                            fact.add(newInstance(prop, pp[i]));
110                        }
111                    } catch (SaslException e) {
112                        // ignore this factory
113                        e.printStackTrace();
114                    }
115                }
116            }
117        }
118        return fact;
119    }
120
121    @SuppressWarnings("unchecked")
122    public static Enumeration<SaslClientFactory> getSaslClientFactories() {
123        Collection<SaslClientFactory> res = (Collection<SaslClientFactory>) findFactories(CLIENTFACTORYSRV);
124        return Collections.enumeration(res);
125
126    }
127
128    @SuppressWarnings("unchecked")
129    public static Enumeration<SaslServerFactory> getSaslServerFactories() {
130        Collection<SaslServerFactory> res = (Collection<SaslServerFactory>) findFactories(SERVERFACTORYSRV);
131        return Collections.enumeration(res);
132    }
133
134    public static SaslServer createSaslServer(String mechanism, String protocol,
135            String serverName, Map<String, ?> prop, CallbackHandler cbh) throws SaslException {
136        if (mechanism == null) {
137            throw new NullPointerException("auth.32"); //$NON-NLS-1$
138        }
139        Collection<?> res = findFactories(SERVERFACTORYSRV);
140        if (res.isEmpty()) {
141            return null;
142        }
143
144        Iterator<?> iter = res.iterator();
145        while (iter.hasNext()) {
146            SaslServerFactory fact = (SaslServerFactory) iter.next();
147            String[] mech = fact.getMechanismNames(null);
148            boolean is = false;
149            if (mech != null) {
150                for (int j = 0; j < mech.length; j++) {
151                    if (mech[j].equals(mechanism)) {
152                        is = true;
153                        break;
154                    }
155                }
156            }
157            if (is) {
158                SaslServer saslS = fact.createSaslServer(mechanism, protocol, serverName, prop,
159                        cbh);
160                if (saslS != null) {
161                    return saslS;
162                }
163            }
164        }
165        return null;
166    }
167
168    public static SaslClient createSaslClient(String[] mechanisms, String authanticationID,
169            String protocol, String serverName, Map<String, ?> prop, CallbackHandler cbh)
170            throws SaslException {
171        if (mechanisms == null) {
172            throw new NullPointerException("auth.33"); //$NON-NLS-1$
173        }
174        Collection<?> res = findFactories(CLIENTFACTORYSRV);
175        if (res.isEmpty()) {
176            return null;
177        }
178
179        Iterator<?> iter = res.iterator();
180        while (iter.hasNext()) {
181            SaslClientFactory fact = (SaslClientFactory) iter.next();
182            String[] mech = fact.getMechanismNames(null);
183            boolean is = false;
184            if (mech != null) {
185                for (int j = 0; j < mech.length; j++) {
186                    for (int n = 0; n < mechanisms.length; n++) {
187                        if (mech[j].equals(mechanisms[n])) {
188                            is = true;
189                            break;
190                        }
191                    }
192                }
193            }
194            if (is) {
195                SaslClient saslC = fact.createSaslClient(mechanisms, authanticationID,
196                        protocol, serverName, prop, cbh);
197                if (saslC != null) {
198                    return saslC;
199                }
200            }
201        }
202        return null;
203    }
204}
205