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.internal.kerberos.v5;
019:
020: import java.io.ByteArrayOutputStream;
021: import java.io.IOException;
022: import java.net.DatagramPacket;
023: import java.net.DatagramSocket;
024: import java.net.InetAddress;
025:
026: import javax.security.auth.kerberos.KerberosKey;
027: import javax.security.auth.kerberos.KerberosPrincipal;
028:
029: import org.apache.harmony.auth.internal.nls.Messages;
030: import org.apache.harmony.security.asn1.DerInputStream;
031:
032: /**
033: * @see http://www.ietf.org/rfc/rfc4120.txt
034: */
035: public class KrbClient {
036:
037: // default kdc server
038: private static final String DEFAULT_KDC = "java.security.krb5.kdc"; //$NON-NLS-1$
039:
040: // default realm
041: private static final String DEFAULT_REALM = "java.security.krb5.realm"; //$NON-NLS-1$
042:
043: private static String kdc;
044:
045: private static String realm;
046:
047: private static int port = 88;//default
048:
049: private static final int BUF_SIZE = 1024;
050:
051: private static boolean isInitialized = false;
052:
053: private KrbClient() {
054: // no objects
055: }
056:
057: public static synchronized String getRealm()
058: throws KerberosException {
059: if (!isInitialized) {
060: setEnv();
061: }
062: return realm;
063: }
064:
065: private static void setEnv() throws KerberosException {
066: if (isInitialized) {
067: return;
068: }
069:
070: //TODO put in doPrivileged
071: kdc = System.getProperty(DEFAULT_KDC);
072: realm = System.getProperty(DEFAULT_REALM);
073: if (kdc == null && realm != null || kdc != null
074: && realm == null) {
075: // both properties should be set or unset together
076: throw new KerberosException();//FIXME message
077: } else if (kdc == null && realm == null) {
078:
079: // reading config from configuration file 'krb5.conf'
080: KrbConfig config = null;
081: try {
082: config = KrbConfig.getSystemConfig();
083: } catch (IOException e) {
084: throw new KerberosException(e.getMessage());
085: }
086:
087: if (config == null) {
088: // no config file was found
089: throw new KerberosException();//FIXME err msg
090: }
091: realm = config.getValue("libdefaults", //$NON-NLS-1$
092: "default_realm"); //$NON-NLS-1$
093:
094: //TODO set KDC
095: return;
096: }
097:
098: int pos = kdc.indexOf(':');
099: if (pos != -1) {
100: port = Integer.parseInt(kdc.substring(pos + 1));
101: kdc = kdc.substring(0, pos);
102: }
103:
104: isInitialized = true;
105: }
106:
107: /**
108: * Get credentials from Authentication Service.
109: *
110: * @param address - service host
111: * @param port - service port
112: * @param cname - client's principal identifier
113: * @param realm - client's realm
114: * @return - ticket
115: */
116: public static KDCReply doAS(PrincipalName cname, char[] password)
117: throws KerberosException {
118:
119: setEnv();
120:
121: PrincipalName sname = new PrincipalName(
122: PrincipalName.NT_SRV_XHST, new String[] {
123: "krbtgt", realm }); //$NON-NLS-1$
124:
125: KDCRequest request = new KDCRequest(KDCRequest.AS_REQ, cname,
126: realm, sname);
127:
128: try {
129: DatagramSocket socket = request.send(InetAddress
130: .getByName(kdc), port);
131:
132: ByteArrayOutputStream out = new ByteArrayOutputStream(
133: BUF_SIZE);
134:
135: byte[] buf = new byte[BUF_SIZE];
136:
137: DatagramPacket resp = new DatagramPacket(buf, buf.length);
138:
139: int bytesRead = BUF_SIZE;
140: while (bytesRead == BUF_SIZE) {
141: socket.receive(resp);
142:
143: bytesRead = resp.getLength();
144: out.write(buf, resp.getOffset(), bytesRead);
145: }
146: DerInputStream in = new DerInputStream(out.toByteArray());
147:
148: if (in.tag == KDCReply.AS_REP_ASN1.constrId) { //TODO AS reply
149: KDCReply reply = (KDCReply) KDCReply.AS_REP_ASN1
150: .decode(in);
151:
152: KerberosKey key = new KerberosKey(
153: new KerberosPrincipal(cname.getName()[0] + '@'
154: + realm, cname.getType()), password,
155: "DES");
156:
157: reply.decrypt(key);
158:
159: return reply;
160: } else if (in.tag == KerberosErrorMessage.ASN1.constrId) {
161: KerberosErrorMessage errMsg = KerberosErrorMessage
162: .decode(in);
163: // auth.52=Error code: {0}
164: throw new KerberosException(Messages.getString(
165: "auth.52", errMsg.getErrorCode())); //$NON-NLS-1$
166: } else {
167: new KerberosException(); //FIXME
168: }
169:
170: } catch (IOException e) {
171: new KerberosException(e.getMessage()); //FIXME
172: }
173:
174: return null;
175: }
176:
177: public static KDCReply doTGS() throws KerberosException {
178: setEnv();
179:
180: return null;
181: }
182: }
|