| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| package org.apache.kerby.kerberos.tool.kinit; |
| |
| import org.apache.kerby.KOption; |
| import org.apache.kerby.KOptionGroup; |
| import org.apache.kerby.KOptionInfo; |
| import org.apache.kerby.KOptionType; |
| import org.apache.kerby.KOptions; |
| import org.apache.kerby.kerberos.kerb.KrbException; |
| import org.apache.kerby.kerberos.kerb.client.KrbClient; |
| import org.apache.kerby.kerberos.kerb.client.KrbKdcOption; |
| import org.apache.kerby.kerberos.kerb.client.KrbOption; |
| import org.apache.kerby.kerberos.kerb.client.KrbOptionGroup; |
| import org.apache.kerby.kerberos.kerb.client.PkinitOption; |
| import org.apache.kerby.kerberos.kerb.client.TokenOption; |
| import org.apache.kerby.util.OSUtil; |
| |
| import java.io.File; |
| import java.util.concurrent.locks.Lock; |
| import java.util.concurrent.locks.ReentrantLock; |
| |
| /** |
| * kinit like tool with concurrence |
| * |
| * Ref. MIT kinit command tool usage.aa |
| */ |
| public class KinitToolWithConcurrence { |
| /** |
| * control the number of request |
| */ |
| private static int[] reList = new int[100000]; |
| private static String[] prList = new String[10000]; |
| private static KOptions ktOptions = new KOptions(); |
| private static int thFlag = 0; |
| private static Long startTime = 0L; |
| private static Lock lock = new ReentrantLock(); |
| private static int tmpTotals = 0; |
| private static final int INTERVAL = 16; |
| |
| private static final String USAGE = (OSUtil.isWindows() |
| ? "Usage: bin\\kinit.cmd" : "Usage: sh bin/kinit.sh") |
| + " <-conf conf_dir> [-V] [-l lifetime] [-s start_time]\n" |
| + "\t\t[-r renewable_life] [-f | -F] [-p | -P] -n [-a | -A] [-C] [-E]\n" |
| + "\t\t[-v] [-R] [-k [-i|-t keytab_file]] [-c cachename]\n" |
| + "\t\t[-S service_name] [-T ticket_armor_cache]\n" |
| + "\t\t[-X <attribute>[=<value>]] <principal>\n\n" |
| + "\tDESCRIPTION:\n" |
| + "\t\tkinit obtains and caches an initial ticket-granting ticket for principal.\n\n" |
| + "\tOPTIONS:\n" |
| + "\t\t-V verbose\n" |
| + "\t\t-l lifetime\n" |
| + "\t\t--s start time\n" |
| + "\t\t-r renewable lifetime\n" |
| + "\t\t-f forwardable\n" |
| + "\t\t-F not forwardable\n" |
| + "\t\t-p proxiable\n" |
| + "\t\t-P not proxiable\n" |
| + "\t\t-n anonymous\n" |
| + "\t\t-a include addresses\n" |
| + "\t\t-A do not include addresses\n" |
| + "\t\t-v validate\n" |
| + "\t\t-R renew\n" |
| + "\t\t-C canonicalize\n" |
| + "\t\t-E client is enterprise principal name\n" |
| + "\t\t-k use keytab\n" |
| + "\t\t-i use default client keytab (with -k)\n" |
| + "\t\t-t filename of keytab to use\n" |
| + "\t\t-c Kerberos 5 cache name\n" |
| + "\t\t-S service\n" |
| + "\t\t-T armor credential cache\n" |
| + "\t\t-X <attribute>[=<value>]\n" |
| + "\n"; |
| |
| |
| private static void printUsage(String error) { |
| System.err.println(error + "\n"); |
| System.err.println(USAGE); |
| System.exit(-1); |
| } |
| |
| private static void requestTicket(String principal, |
| KOptions ktOptions, int flag) { |
| ktOptions.add(KinitOption.CLIENT_PRINCIPAL, principal); |
| |
| File confDir = null; |
| if (ktOptions.contains(KinitOption.CONF_DIR)) { |
| confDir = ktOptions.getDirOption(KinitOption.CONF_DIR); |
| } |
| |
| if (ktOptions.contains(KinitOption.ANONYMOUS)) { |
| ktOptions.add(PkinitOption.USE_ANONYMOUS); |
| ktOptions.add(PkinitOption.X509_ANCHORS); |
| } else if (!ktOptions.contains(KinitOption.USE_KEYTAB)) { |
| //If not request tickets by keytab than by password. |
| ktOptions.add(KinitOption.USE_PASSWD); |
| String password = "12"; |
| ktOptions.add(KinitOption.USER_PASSWD, password); |
| } |
| |
| KrbClient krbClient = null; |
| try { |
| krbClient = getClient(confDir); |
| } catch (KrbException e) { |
| System.err.println("Create krbClient failed: " + e.getMessage()); |
| System.exit(1); |
| } |
| |
| KOptions results = convertOptions(ktOptions); |
| try { |
| flag *= INTERVAL; |
| while (true) { |
| krbClient.requestTgt(results); |
| reList[flag] += 1; |
| } |
| } catch (KrbException e) { |
| System.err.println("Authentication failed: " + e.getMessage()); |
| System.exit(1); |
| } |
| } |
| |
| /** |
| * Init the client. |
| */ |
| private static KrbClient getClient(File confDir) throws KrbException { |
| KrbClient krbClient; |
| |
| if (confDir != null) { |
| krbClient = new KrbClient(confDir); |
| } else { |
| krbClient = new KrbClient(); |
| } |
| |
| krbClient.init(); |
| return krbClient; |
| } |
| |
| public static void main(String[] args) throws Exception { |
| KinitOption kto; |
| String principalNumbers = null; |
| String startIndex = null; |
| |
| int i = 0; |
| String opt, param, error; |
| while (i < args.length) { |
| error = null; |
| |
| opt = args[i++]; |
| if (opt.startsWith("-")) { |
| kto = KinitOption.fromName(opt); |
| if (kto == KinitOption.NONE) { |
| error = "Invalid option:" + opt; |
| System.err.println(error); |
| break; |
| } |
| } else { |
| principalNumbers = opt; |
| kto = KinitOption.NONE; |
| // require a parameter |
| startIndex = args[i++]; |
| } |
| |
| if (kto != KinitOption.NONE && kto.getOptionInfo().getType() != KOptionType.NOV) { |
| // require a parameter |
| param = null; |
| if (i < args.length) { |
| param = args[i++]; |
| } |
| if (param != null) { |
| KOptions.parseSetValue(kto.getOptionInfo(), param); |
| } else { |
| error = "Option " + opt + " require a parameter"; |
| } |
| } |
| |
| if (error != null) { |
| printUsage(error); |
| } |
| if (kto != KinitOption.NONE) { |
| ktOptions.add(kto); |
| } |
| } |
| |
| int threadNumbers = Integer.parseInt(principalNumbers); |
| int stIndex = Integer.parseInt(startIndex); |
| |
| if (threadNumbers <= 0) { |
| printUsage("principal must be greater than zero"); |
| System.exit(-1); |
| } |
| |
| for (int j = 0; j < threadNumbers; j++) { |
| int tmpIndex = j + stIndex; |
| String tempName = "E" + tmpIndex + "@EXAMPLE.COM"; |
| prList[j] = tempName; |
| } |
| |
| for (int j = 0; j < threadNumbers; j++) { |
| Thread th = new Thread(new PreThread()); |
| th.start(); |
| } |
| |
| // statistical |
| int[] tempDelayNumbers = new int[threadNumbers]; |
| int[] delayNumbers = new int[threadNumbers]; |
| startTime = System.currentTimeMillis(); |
| long timeStamp = System.currentTimeMillis(); |
| |
| int max = 0; |
| int min = 0; |
| |
| System.out.println("Time stamp (sec),Throughput (sec)," |
| + "avgDelay (ms),maxDelay (ms),minDelay (ms)"); |
| |
| while (true) { |
| Thread.sleep(2000); |
| int temp = 0; |
| long now = System.currentTimeMillis(); |
| |
| for (int j = 0; j < threadNumbers; j++) { |
| delayNumbers[j] = reList[j * INTERVAL] - tempDelayNumbers[j]; |
| tempDelayNumbers[j] = reList[j * INTERVAL]; |
| } |
| |
| for (int j = 0; j < threadNumbers; j++) { |
| temp += reList[j * INTERVAL]; |
| } |
| float res = (now - startTime) / (float) 1000; |
| |
| double totalDelay = 0.0; |
| int cutThreads = 0; |
| for (int j = 0; j < threadNumbers; j++) { |
| if (delayNumbers[j] != 0) { |
| if (delayNumbers[max] < delayNumbers[j]) { |
| max = j; |
| } |
| if (delayNumbers[min] == 0 || delayNumbers[min] > delayNumbers[j]) { |
| min = j; |
| } |
| totalDelay += (now - startTime) * 1.0 / delayNumbers[j]; |
| } else { |
| cutThreads += 1; |
| } |
| } |
| if (delayNumbers[min] != 0 && delayNumbers[max] != 0) { |
| System.out.println((now - timeStamp) / 1000 + "," + (temp - tmpTotals) / res |
| + "," + (int) (totalDelay / (threadNumbers - cutThreads)) |
| + "," + (now - startTime) / delayNumbers[min] + "," + (now - startTime) / delayNumbers[max]); |
| } |
| |
| tmpTotals = temp; |
| startTime = now; |
| } |
| |
| } |
| |
| public static class PreThread implements Runnable { |
| @Override |
| public void run() { |
| request(); |
| } |
| } |
| |
| public static void request() { |
| int tempFlag = 0; |
| lock.lock(); |
| tempFlag = thFlag; |
| thFlag++; |
| lock.unlock(); |
| requestTicket(prList[tempFlag], ktOptions, tempFlag); |
| } |
| |
| /** |
| * Convert kinit tool options to KOptions. |
| * @param toolOptions |
| * @return KOptions |
| */ |
| static KOptions convertOptions(KOptions toolOptions) { |
| KOptions results = new KOptions(); |
| |
| for (KOption toolOpt : toolOptions.getOptions()) { |
| KOptionInfo kOptionInfo = toolOpt.getOptionInfo(); |
| KOptionGroup group = kOptionInfo.getGroup(); |
| KOption kOpt = null; |
| |
| if (group == KrbOptionGroup.KRB) { |
| kOpt = KrbOption.fromOptionName(kOptionInfo.getName()); |
| } else if (group == KrbOptionGroup.PKINIT) { |
| kOpt = PkinitOption.fromOptionName(kOptionInfo.getName()); |
| } else if (group == KrbOptionGroup.TOKEN) { |
| kOpt = TokenOption.fromOptionName(kOptionInfo.getName()); |
| } else if (group == KrbOptionGroup.KDC_FLAGS) { |
| kOpt = KrbKdcOption.fromOptionName(kOptionInfo.getName()); |
| } |
| if (kOpt != null && kOpt.getOptionInfo() != KrbOption.NONE.getOptionInfo()) { |
| kOpt.getOptionInfo().setValue(toolOpt.getOptionInfo().getValue()); |
| results.add(kOpt); |
| } |
| } |
| |
| return results; |
| } |
| |
| } |