001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with this 004 * work for additional information regarding copyright ownership. The ASF 005 * licenses this file to you under the Apache License, Version 2.0 (the 006 * "License"); you may not use this file except in compliance with the License. 007 * 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, WITHOUT 013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 014 * License for the specific language governing permissions and limitations under 015 * the License. 016 */ 017package org.apache.hadoop.security; 018 019import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION; 020import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_DNS_INTERFACE_KEY; 021import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_DNS_NAMESERVER_KEY; 022 023import java.io.IOException; 024import java.net.InetAddress; 025import java.net.InetSocketAddress; 026import java.net.URI; 027import java.net.UnknownHostException; 028import java.security.PrivilegedAction; 029import java.security.PrivilegedExceptionAction; 030import java.util.Arrays; 031import java.util.List; 032import java.util.ServiceLoader; 033import java.util.concurrent.TimeUnit; 034 035import javax.annotation.Nullable; 036import javax.security.auth.kerberos.KerberosPrincipal; 037import javax.security.auth.kerberos.KerberosTicket; 038 039import org.apache.commons.logging.Log; 040import org.apache.commons.logging.LogFactory; 041import org.apache.hadoop.classification.InterfaceAudience; 042import org.apache.hadoop.classification.InterfaceStability; 043import org.apache.hadoop.conf.Configuration; 044import org.apache.hadoop.fs.CommonConfigurationKeys; 045import org.apache.hadoop.io.Text; 046import org.apache.hadoop.net.DNS; 047import org.apache.hadoop.net.NetUtils; 048import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod; 049import org.apache.hadoop.security.token.Token; 050import org.apache.hadoop.security.token.TokenInfo; 051import org.apache.hadoop.util.StopWatch; 052import org.apache.hadoop.util.StringUtils; 053 054 055//this will need to be replaced someday when there is a suitable replacement 056import sun.net.dns.ResolverConfiguration; 057import sun.net.util.IPAddressUtil; 058 059import com.google.common.annotations.VisibleForTesting; 060 061/** 062 * Security Utils. 063 */ 064@InterfaceAudience.Public 065@InterfaceStability.Evolving 066public final class SecurityUtil { 067 public static final Log LOG = LogFactory.getLog(SecurityUtil.class); 068 public static final String HOSTNAME_PATTERN = "_HOST"; 069 public static final String FAILED_TO_GET_UGI_MSG_HEADER = 070 "Failed to obtain user group information:"; 071 072 private SecurityUtil() { 073 } 074 075 // controls whether buildTokenService will use an ip or host/ip as given 076 // by the user 077 @VisibleForTesting 078 static boolean useIpForTokenService; 079 @VisibleForTesting 080 static HostResolver hostResolver; 081 082 static { 083 Configuration conf = new Configuration(); 084 boolean useIp = conf.getBoolean( 085 CommonConfigurationKeys.HADOOP_SECURITY_TOKEN_SERVICE_USE_IP, 086 CommonConfigurationKeys.HADOOP_SECURITY_TOKEN_SERVICE_USE_IP_DEFAULT); 087 setTokenServiceUseIp(useIp); 088 } 089 090 private static boolean logSlowLookups = getLogSlowLookupsEnabled(); 091 private static int slowLookupThresholdMs = getSlowLookupThresholdMs(); 092 093 /** 094 * For use only by tests and initialization 095 */ 096 @InterfaceAudience.Private 097 @VisibleForTesting 098 public static void setTokenServiceUseIp(boolean flag) { 099 useIpForTokenService = flag; 100 hostResolver = !useIpForTokenService 101 ? new QualifiedHostResolver() 102 : new StandardHostResolver(); 103 } 104 105 /** 106 * TGS must have the server principal of the form "krbtgt/FOO@FOO". 107 * @param principal 108 * @return true or false 109 */ 110 static boolean 111 isTGSPrincipal(KerberosPrincipal principal) { 112 if (principal == null) 113 return false; 114 if (principal.getName().equals("krbtgt/" + principal.getRealm() + 115 "@" + principal.getRealm())) { 116 return true; 117 } 118 return false; 119 } 120 121 /** 122 * Check whether the server principal is the TGS's principal 123 * @param ticket the original TGT (the ticket that is obtained when a 124 * kinit is done) 125 * @return true or false 126 */ 127 protected static boolean isOriginalTGT(KerberosTicket ticket) { 128 return isTGSPrincipal(ticket.getServer()); 129 } 130 131 /** 132 * Convert Kerberos principal name pattern to valid Kerberos principal 133 * names. It replaces hostname pattern with hostname, which should be 134 * fully-qualified domain name. If hostname is null or "0.0.0.0", it uses 135 * dynamically looked-up fqdn of the current host instead. 136 * 137 * @param principalConfig 138 * the Kerberos principal name conf value to convert 139 * @param hostname 140 * the fully-qualified domain name used for substitution 141 * @return converted Kerberos principal name 142 * @throws IOException if the client address cannot be determined 143 */ 144 @InterfaceAudience.Public 145 @InterfaceStability.Evolving 146 public static String getServerPrincipal(String principalConfig, 147 String hostname) throws IOException { 148 String[] components = getComponents(principalConfig); 149 if (components == null || components.length != 3 150 || !components[1].equals(HOSTNAME_PATTERN)) { 151 return principalConfig; 152 } else { 153 return replacePattern(components, hostname); 154 } 155 } 156 157 /** 158 * Convert Kerberos principal name pattern to valid Kerberos principal names. 159 * This method is similar to {@link #getServerPrincipal(String, String)}, 160 * except 1) the reverse DNS lookup from addr to hostname is done only when 161 * necessary, 2) param addr can't be null (no default behavior of using local 162 * hostname when addr is null). 163 * 164 * @param principalConfig 165 * Kerberos principal name pattern to convert 166 * @param addr 167 * InetAddress of the host used for substitution 168 * @return converted Kerberos principal name 169 * @throws IOException if the client address cannot be determined 170 */ 171 @InterfaceAudience.Public 172 @InterfaceStability.Evolving 173 public static String getServerPrincipal(String principalConfig, 174 InetAddress addr) throws IOException { 175 String[] components = getComponents(principalConfig); 176 if (components == null || components.length != 3 177 || !components[1].equals(HOSTNAME_PATTERN)) { 178 return principalConfig; 179 } else { 180 if (addr == null) { 181 throw new IOException("Can't replace " + HOSTNAME_PATTERN 182 + " pattern since client address is null"); 183 } 184 return replacePattern(components, addr.getCanonicalHostName()); 185 } 186 } 187 188 private static String[] getComponents(String principalConfig) { 189 if (principalConfig == null) 190 return null; 191 return principalConfig.split("[/@]"); 192 } 193 194 private static String replacePattern(String[] components, String hostname) 195 throws IOException { 196 String fqdn = hostname; 197 if (fqdn == null || fqdn.isEmpty() || fqdn.equals("0.0.0.0")) { 198 fqdn = getLocalHostName(null); 199 } 200 return components[0] + "/" + 201 StringUtils.toLowerCase(fqdn) + "@" + components[2]; 202 } 203 204 /** 205 * Retrieve the name of the current host. Multihomed hosts may restrict the 206 * hostname lookup to a specific interface and nameserver with {@link 207 * org.apache.hadoop.fs.CommonConfigurationKeysPublic#HADOOP_SECURITY_DNS_INTERFACE_KEY} 208 * and {@link org.apache.hadoop.fs.CommonConfigurationKeysPublic#HADOOP_SECURITY_DNS_NAMESERVER_KEY} 209 * 210 * @param conf Configuration object. May be null. 211 * @return 212 * @throws UnknownHostException 213 */ 214 static String getLocalHostName(@Nullable Configuration conf) 215 throws UnknownHostException { 216 if (conf != null) { 217 String dnsInterface = conf.get(HADOOP_SECURITY_DNS_INTERFACE_KEY); 218 String nameServer = conf.get(HADOOP_SECURITY_DNS_NAMESERVER_KEY); 219 220 if (dnsInterface != null) { 221 return DNS.getDefaultHost(dnsInterface, nameServer, true); 222 } else if (nameServer != null) { 223 throw new IllegalArgumentException(HADOOP_SECURITY_DNS_NAMESERVER_KEY + 224 " requires " + HADOOP_SECURITY_DNS_INTERFACE_KEY + ". Check your" + 225 "configuration."); 226 } 227 } 228 229 // Fallback to querying the default hostname as we did before. 230 return InetAddress.getLocalHost().getCanonicalHostName(); 231 } 232 233 /** 234 * Login as a principal specified in config. Substitute $host in 235 * user's Kerberos principal name with a dynamically looked-up fully-qualified 236 * domain name of the current host. 237 * 238 * @param conf 239 * conf to use 240 * @param keytabFileKey 241 * the key to look for keytab file in conf 242 * @param userNameKey 243 * the key to look for user's Kerberos principal name in conf 244 * @throws IOException if login fails 245 */ 246 @InterfaceAudience.Public 247 @InterfaceStability.Evolving 248 public static void login(final Configuration conf, 249 final String keytabFileKey, final String userNameKey) throws IOException { 250 login(conf, keytabFileKey, userNameKey, getLocalHostName(conf)); 251 } 252 253 /** 254 * Login as a principal specified in config. Substitute $host in user's Kerberos principal 255 * name with hostname. If non-secure mode - return. If no keytab available - 256 * bail out with an exception 257 * 258 * @param conf 259 * conf to use 260 * @param keytabFileKey 261 * the key to look for keytab file in conf 262 * @param userNameKey 263 * the key to look for user's Kerberos principal name in conf 264 * @param hostname 265 * hostname to use for substitution 266 * @throws IOException if the config doesn't specify a keytab 267 */ 268 @InterfaceAudience.Public 269 @InterfaceStability.Evolving 270 public static void login(final Configuration conf, 271 final String keytabFileKey, final String userNameKey, String hostname) 272 throws IOException { 273 274 if(! UserGroupInformation.isSecurityEnabled()) 275 return; 276 277 String keytabFilename = conf.get(keytabFileKey); 278 if (keytabFilename == null || keytabFilename.length() == 0) { 279 throw new IOException("Running in secure mode, but config doesn't have a keytab"); 280 } 281 282 String principalConfig = conf.get(userNameKey, System 283 .getProperty("user.name")); 284 String principalName = SecurityUtil.getServerPrincipal(principalConfig, 285 hostname); 286 UserGroupInformation.loginUserFromKeytab(principalName, keytabFilename); 287 } 288 289 /** 290 * create the service name for a Delegation token 291 * @param uri of the service 292 * @param defPort is used if the uri lacks a port 293 * @return the token service, or null if no authority 294 * @see #buildTokenService(InetSocketAddress) 295 */ 296 public static String buildDTServiceName(URI uri, int defPort) { 297 String authority = uri.getAuthority(); 298 if (authority == null) { 299 return null; 300 } 301 InetSocketAddress addr = NetUtils.createSocketAddr(authority, defPort); 302 return buildTokenService(addr).toString(); 303 } 304 305 /** 306 * Get the host name from the principal name of format <service>/host@realm. 307 * @param principalName principal name of format as described above 308 * @return host name if the the string conforms to the above format, else null 309 */ 310 public static String getHostFromPrincipal(String principalName) { 311 return new HadoopKerberosName(principalName).getHostName(); 312 } 313 314 private static ServiceLoader<SecurityInfo> securityInfoProviders = 315 ServiceLoader.load(SecurityInfo.class); 316 private static SecurityInfo[] testProviders = new SecurityInfo[0]; 317 318 /** 319 * Test setup method to register additional providers. 320 * @param providers a list of high priority providers to use 321 */ 322 @InterfaceAudience.Private 323 public static void setSecurityInfoProviders(SecurityInfo... providers) { 324 testProviders = providers; 325 } 326 327 /** 328 * Look up the KerberosInfo for a given protocol. It searches all known 329 * SecurityInfo providers. 330 * @param protocol the protocol class to get the information for 331 * @param conf configuration object 332 * @return the KerberosInfo or null if it has no KerberosInfo defined 333 */ 334 public static KerberosInfo 335 getKerberosInfo(Class<?> protocol, Configuration conf) { 336 for(SecurityInfo provider: testProviders) { 337 KerberosInfo result = provider.getKerberosInfo(protocol, conf); 338 if (result != null) { 339 return result; 340 } 341 } 342 343 synchronized (securityInfoProviders) { 344 for(SecurityInfo provider: securityInfoProviders) { 345 KerberosInfo result = provider.getKerberosInfo(protocol, conf); 346 if (result != null) { 347 return result; 348 } 349 } 350 } 351 return null; 352 } 353 354 /** 355 * Look up the TokenInfo for a given protocol. It searches all known 356 * SecurityInfo providers. 357 * @param protocol The protocol class to get the information for. 358 * @param conf Configuration object 359 * @return the TokenInfo or null if it has no KerberosInfo defined 360 */ 361 public static TokenInfo getTokenInfo(Class<?> protocol, Configuration conf) { 362 for(SecurityInfo provider: testProviders) { 363 TokenInfo result = provider.getTokenInfo(protocol, conf); 364 if (result != null) { 365 return result; 366 } 367 } 368 369 synchronized (securityInfoProviders) { 370 for(SecurityInfo provider: securityInfoProviders) { 371 TokenInfo result = provider.getTokenInfo(protocol, conf); 372 if (result != null) { 373 return result; 374 } 375 } 376 } 377 378 return null; 379 } 380 381 /** 382 * Decode the given token's service field into an InetAddress 383 * @param token from which to obtain the service 384 * @return InetAddress for the service 385 */ 386 public static InetSocketAddress getTokenServiceAddr(Token<?> token) { 387 return NetUtils.createSocketAddr(token.getService().toString()); 388 } 389 390 /** 391 * Set the given token's service to the format expected by the RPC client 392 * @param token a delegation token 393 * @param addr the socket for the rpc connection 394 */ 395 public static void setTokenService(Token<?> token, InetSocketAddress addr) { 396 Text service = buildTokenService(addr); 397 if (token != null) { 398 token.setService(service); 399 if (LOG.isDebugEnabled()) { 400 LOG.debug("Acquired token "+token); // Token#toString() prints service 401 } 402 } else { 403 LOG.warn("Failed to get token for service "+service); 404 } 405 } 406 407 /** 408 * Construct the service key for a token 409 * @param addr InetSocketAddress of remote connection with a token 410 * @return "ip:port" or "host:port" depending on the value of 411 * hadoop.security.token.service.use_ip 412 */ 413 public static Text buildTokenService(InetSocketAddress addr) { 414 String host = null; 415 if (useIpForTokenService) { 416 if (addr.isUnresolved()) { // host has no ip address 417 throw new IllegalArgumentException( 418 new UnknownHostException(addr.getHostName()) 419 ); 420 } 421 host = addr.getAddress().getHostAddress(); 422 } else { 423 host = StringUtils.toLowerCase(addr.getHostName()); 424 } 425 return new Text(host + ":" + addr.getPort()); 426 } 427 428 /** 429 * Construct the service key for a token 430 * @param uri of remote connection with a token 431 * @return "ip:port" or "host:port" depending on the value of 432 * hadoop.security.token.service.use_ip 433 */ 434 public static Text buildTokenService(URI uri) { 435 return buildTokenService(NetUtils.createSocketAddr(uri.getAuthority())); 436 } 437 438 /** 439 * Perform the given action as the daemon's login user. If the login 440 * user cannot be determined, this will log a FATAL error and exit 441 * the whole JVM. 442 */ 443 public static <T> T doAsLoginUserOrFatal(PrivilegedAction<T> action) { 444 if (UserGroupInformation.isSecurityEnabled()) { 445 UserGroupInformation ugi = null; 446 try { 447 ugi = UserGroupInformation.getLoginUser(); 448 } catch (IOException e) { 449 LOG.fatal("Exception while getting login user", e); 450 e.printStackTrace(); 451 Runtime.getRuntime().exit(-1); 452 } 453 return ugi.doAs(action); 454 } else { 455 return action.run(); 456 } 457 } 458 459 /** 460 * Perform the given action as the daemon's login user. If an 461 * InterruptedException is thrown, it is converted to an IOException. 462 * 463 * @param action the action to perform 464 * @return the result of the action 465 * @throws IOException in the event of error 466 */ 467 public static <T> T doAsLoginUser(PrivilegedExceptionAction<T> action) 468 throws IOException { 469 return doAsUser(UserGroupInformation.getLoginUser(), action); 470 } 471 472 /** 473 * Perform the given action as the daemon's current user. If an 474 * InterruptedException is thrown, it is converted to an IOException. 475 * 476 * @param action the action to perform 477 * @return the result of the action 478 * @throws IOException in the event of error 479 */ 480 public static <T> T doAsCurrentUser(PrivilegedExceptionAction<T> action) 481 throws IOException { 482 return doAsUser(UserGroupInformation.getCurrentUser(), action); 483 } 484 485 private static <T> T doAsUser(UserGroupInformation ugi, 486 PrivilegedExceptionAction<T> action) throws IOException { 487 try { 488 return ugi.doAs(action); 489 } catch (InterruptedException ie) { 490 throw new IOException(ie); 491 } 492 } 493 494 private static boolean getLogSlowLookupsEnabled() { 495 Configuration conf = new Configuration(); 496 497 return conf.getBoolean(CommonConfigurationKeys 498 .HADOOP_SECURITY_DNS_LOG_SLOW_LOOKUPS_ENABLED_KEY, 499 CommonConfigurationKeys 500 .HADOOP_SECURITY_DNS_LOG_SLOW_LOOKUPS_ENABLED_DEFAULT); 501 } 502 503 private static int getSlowLookupThresholdMs() { 504 Configuration conf = new Configuration(); 505 506 return conf.getInt(CommonConfigurationKeys 507 .HADOOP_SECURITY_DNS_LOG_SLOW_LOOKUPS_THRESHOLD_MS_KEY, 508 CommonConfigurationKeys 509 .HADOOP_SECURITY_DNS_LOG_SLOW_LOOKUPS_THRESHOLD_MS_DEFAULT); 510 } 511 512 /** 513 * Resolves a host subject to the security requirements determined by 514 * hadoop.security.token.service.use_ip. Optionally logs slow resolutions. 515 * 516 * @param hostname host or ip to resolve 517 * @return a resolved host 518 * @throws UnknownHostException if the host doesn't exist 519 */ 520 @InterfaceAudience.Private 521 public static 522 InetAddress getByName(String hostname) throws UnknownHostException { 523 if (logSlowLookups || LOG.isTraceEnabled()) { 524 StopWatch lookupTimer = new StopWatch().start(); 525 InetAddress result = hostResolver.getByName(hostname); 526 long elapsedMs = lookupTimer.stop().now(TimeUnit.MILLISECONDS); 527 528 if (elapsedMs >= slowLookupThresholdMs) { 529 LOG.warn("Slow name lookup for " + hostname + ". Took " + elapsedMs + 530 " ms."); 531 } else if (LOG.isTraceEnabled()) { 532 LOG.trace("Name lookup for " + hostname + " took " + elapsedMs + 533 " ms."); 534 } 535 return result; 536 } else { 537 return hostResolver.getByName(hostname); 538 } 539 } 540 541 interface HostResolver { 542 InetAddress getByName(String host) throws UnknownHostException; 543 } 544 545 /** 546 * Uses standard java host resolution 547 */ 548 static class StandardHostResolver implements HostResolver { 549 @Override 550 public InetAddress getByName(String host) throws UnknownHostException { 551 return InetAddress.getByName(host); 552 } 553 } 554 555 /** 556 * This an alternate resolver with important properties that the standard 557 * java resolver lacks: 558 * 1) The hostname is fully qualified. This avoids security issues if not 559 * all hosts in the cluster do not share the same search domains. It 560 * also prevents other hosts from performing unnecessary dns searches. 561 * In contrast, InetAddress simply returns the host as given. 562 * 2) The InetAddress is instantiated with an exact host and IP to prevent 563 * further unnecessary lookups. InetAddress may perform an unnecessary 564 * reverse lookup for an IP. 565 * 3) A call to getHostName() will always return the qualified hostname, or 566 * more importantly, the IP if instantiated with an IP. This avoids 567 * unnecessary dns timeouts if the host is not resolvable. 568 * 4) Point 3 also ensures that if the host is re-resolved, ex. during a 569 * connection re-attempt, that a reverse lookup to host and forward 570 * lookup to IP is not performed since the reverse/forward mappings may 571 * not always return the same IP. If the client initiated a connection 572 * with an IP, then that IP is all that should ever be contacted. 573 * 574 * NOTE: this resolver is only used if: 575 * hadoop.security.token.service.use_ip=false 576 */ 577 protected static class QualifiedHostResolver implements HostResolver { 578 @SuppressWarnings("unchecked") 579 private List<String> searchDomains = 580 ResolverConfiguration.open().searchlist(); 581 582 /** 583 * Create an InetAddress with a fully qualified hostname of the given 584 * hostname. InetAddress does not qualify an incomplete hostname that 585 * is resolved via the domain search list. 586 * {@link InetAddress#getCanonicalHostName()} will fully qualify the 587 * hostname, but it always return the A record whereas the given hostname 588 * may be a CNAME. 589 * 590 * @param host a hostname or ip address 591 * @return InetAddress with the fully qualified hostname or ip 592 * @throws UnknownHostException if host does not exist 593 */ 594 @Override 595 public InetAddress getByName(String host) throws UnknownHostException { 596 InetAddress addr = null; 597 598 if (IPAddressUtil.isIPv4LiteralAddress(host)) { 599 // use ipv4 address as-is 600 byte[] ip = IPAddressUtil.textToNumericFormatV4(host); 601 addr = InetAddress.getByAddress(host, ip); 602 } else if (IPAddressUtil.isIPv6LiteralAddress(host)) { 603 // use ipv6 address as-is 604 byte[] ip = IPAddressUtil.textToNumericFormatV6(host); 605 addr = InetAddress.getByAddress(host, ip); 606 } else if (host.endsWith(".")) { 607 // a rooted host ends with a dot, ex. "host." 608 // rooted hosts never use the search path, so only try an exact lookup 609 addr = getByExactName(host); 610 } else if (host.contains(".")) { 611 // the host contains a dot (domain), ex. "host.domain" 612 // try an exact host lookup, then fallback to search list 613 addr = getByExactName(host); 614 if (addr == null) { 615 addr = getByNameWithSearch(host); 616 } 617 } else { 618 // it's a simple host with no dots, ex. "host" 619 // try the search list, then fallback to exact host 620 InetAddress loopback = InetAddress.getByName(null); 621 if (host.equalsIgnoreCase(loopback.getHostName())) { 622 addr = InetAddress.getByAddress(host, loopback.getAddress()); 623 } else { 624 addr = getByNameWithSearch(host); 625 if (addr == null) { 626 addr = getByExactName(host); 627 } 628 } 629 } 630 // unresolvable! 631 if (addr == null) { 632 throw new UnknownHostException(host); 633 } 634 return addr; 635 } 636 637 InetAddress getByExactName(String host) { 638 InetAddress addr = null; 639 // InetAddress will use the search list unless the host is rooted 640 // with a trailing dot. The trailing dot will disable any use of the 641 // search path in a lower level resolver. See RFC 1535. 642 String fqHost = host; 643 if (!fqHost.endsWith(".")) fqHost += "."; 644 try { 645 addr = getInetAddressByName(fqHost); 646 // can't leave the hostname as rooted or other parts of the system 647 // malfunction, ex. kerberos principals are lacking proper host 648 // equivalence for rooted/non-rooted hostnames 649 addr = InetAddress.getByAddress(host, addr.getAddress()); 650 } catch (UnknownHostException e) { 651 // ignore, caller will throw if necessary 652 } 653 return addr; 654 } 655 656 InetAddress getByNameWithSearch(String host) { 657 InetAddress addr = null; 658 if (host.endsWith(".")) { // already qualified? 659 addr = getByExactName(host); 660 } else { 661 for (String domain : searchDomains) { 662 String dot = !domain.startsWith(".") ? "." : ""; 663 addr = getByExactName(host + dot + domain); 664 if (addr != null) break; 665 } 666 } 667 return addr; 668 } 669 670 // implemented as a separate method to facilitate unit testing 671 InetAddress getInetAddressByName(String host) throws UnknownHostException { 672 return InetAddress.getByName(host); 673 } 674 675 void setSearchDomains(String ... domains) { 676 searchDomains = Arrays.asList(domains); 677 } 678 } 679 680 public static AuthenticationMethod getAuthenticationMethod(Configuration conf) { 681 String value = conf.get(HADOOP_SECURITY_AUTHENTICATION, "simple"); 682 try { 683 return Enum.valueOf(AuthenticationMethod.class, 684 StringUtils.toUpperCase(value)); 685 } catch (IllegalArgumentException iae) { 686 throw new IllegalArgumentException("Invalid attribute value for " + 687 HADOOP_SECURITY_AUTHENTICATION + " of " + value); 688 } 689 } 690 691 public static void setAuthenticationMethod( 692 AuthenticationMethod authenticationMethod, Configuration conf) { 693 if (authenticationMethod == null) { 694 authenticationMethod = AuthenticationMethod.SIMPLE; 695 } 696 conf.set(HADOOP_SECURITY_AUTHENTICATION, 697 StringUtils.toLowerCase(authenticationMethod.toString())); 698 } 699 700 /* 701 * Check if a given port is privileged. 702 * The ports with number smaller than 1024 are treated as privileged ports in 703 * unix/linux system. For other operating systems, use this method with care. 704 * For example, Windows doesn't have the concept of privileged ports. 705 * However, it may be used at Windows client to check port of linux server. 706 * 707 * @param port the port number 708 * @return true for privileged ports, false otherwise 709 * 710 */ 711 public static boolean isPrivilegedPort(final int port) { 712 return port < 1024; 713 } 714}