001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.auth.module;
019:
020: import java.util.Map;
021:
022: import javax.security.auth.DestroyFailedException;
023: import javax.security.auth.Subject;
024: import javax.security.auth.callback.Callback;
025: import javax.security.auth.callback.CallbackHandler;
026: import javax.security.auth.callback.PasswordCallback;
027: import javax.security.auth.kerberos.KerberosPrincipal;
028: import javax.security.auth.kerberos.KerberosTicket;
029: import javax.security.auth.login.LoginException;
030: import javax.security.auth.spi.LoginModule;
031:
032: import org.apache.harmony.auth.internal.kerberos.v5.KDCReply;
033: import org.apache.harmony.auth.internal.kerberos.v5.KrbClient;
034: import org.apache.harmony.auth.internal.kerberos.v5.PrincipalName;
035:
036: public class Krb5LoginModule implements LoginModule {
037:
038: // client's principal identifier name
039: private static final String PRINCIPAL = "principal";//$NON-NLS-1$
040:
041: private Subject subject;
042:
043: private Map<String, ?> options;
044:
045: private CallbackHandler callbackHandler;
046:
047: private KerberosPrincipal client;
048:
049: private KerberosTicket krbTicket;
050:
051: public boolean abort() throws LoginException {
052:
053: try {
054: krbTicket.destroy();
055: } catch (DestroyFailedException e) {
056: throw new LoginException();
057: }
058:
059: client = null;
060: krbTicket = null;
061:
062: return true;
063: }
064:
065: public boolean commit() throws LoginException {
066: subject.getPrincipals().add(client);
067: subject.getPrivateCredentials().add(krbTicket);
068: return true;
069: }
070:
071: public void initialize(Subject subject,
072: CallbackHandler callbackHandler,
073: Map<String, ?> sharedState, Map<String, ?> options) {
074: // TODO
075: this .subject = subject;
076: this .options = options;
077: this .callbackHandler = callbackHandler;
078: }
079:
080: public boolean login() throws LoginException {
081:
082: String name = (String) options.get(PRINCIPAL);
083:
084: if (name == null) {
085: throw new LoginException();//FIXME check params
086: }
087:
088: PrincipalName cname = new PrincipalName(
089: PrincipalName.NT_UNKNOWN, new String[] { name });
090:
091: try {
092: // get client's password
093: PasswordCallback callback = new PasswordCallback(
094: "Password for " + name, false);
095: callbackHandler.handle(new Callback[] { callback });
096:
097: KDCReply reply = KrbClient.doAS(cname, callback
098: .getPassword());
099:
100: // add principal to subject
101: String[] pName = reply.getCname().getName();
102: StringBuilder buf = new StringBuilder();
103: for (int i = 0; i < pName.length - 1; i++) {
104: buf.append(pName[i]);
105: buf.append('/');
106: }
107: buf.append(pName[pName.length - 1]);
108: buf.append('@');
109: buf.append(reply.getCrealm());
110:
111: client = new KerberosPrincipal(buf.toString(), reply
112: .getCname().getType());
113:
114: // add ticket to private credentials
115: byte[] ticket = reply.getTicket().getEncoded();
116:
117: String[] sName = reply.getSname().getName();
118: buf = new StringBuilder();
119: for (int i = 0; i < sName.length - 1; i++) {
120: buf.append(sName[i]);
121: buf.append('/');
122: }
123: buf.append(sName[sName.length - 1]);
124: buf.append('@');
125: buf.append(reply.getSrealm());
126:
127: KerberosPrincipal server = new KerberosPrincipal(buf
128: .toString(), reply.getSname().getType());
129:
130: int keyType = reply.getKey().getType();
131: byte[] sessionKey = reply.getKey().getValue();
132:
133: boolean[] flags = reply.getFlags().toBooleanArray();
134:
135: krbTicket = new KerberosTicket(ticket, client, server,
136: sessionKey, keyType, flags, reply.getAuthtime(),
137: reply.getStarttime(), reply.getEndtime(), reply
138: .getRenewtill(),
139: //TODO InetAddress[] clientAddresses
140: null);
141:
142: return true; //FIXME
143: } catch (Exception e) {
144: LoginException ex = new LoginException();
145: ex.initCause(e);
146: throw ex;
147: }
148: }
149:
150: public boolean logout() throws LoginException {
151:
152: subject.getPrincipals().remove(client);
153: subject.getPrivateCredentials().remove(krbTicket);
154:
155: try {
156: krbTicket.destroy();
157: } catch (DestroyFailedException e) {
158: throw new LoginException();
159: }
160:
161: client = null;
162: krbTicket = null;
163:
164: return true;
165: }
166: }
|