You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by om...@apache.org on 2011/03/08 05:37:08 UTC

svn commit: r1079119 [5/5] - in /hadoop/common/branches/yahoo-merge: ./ src/java/org/apache/hadoop/fs/ftp/ src/java/org/apache/hadoop/security/ src/native/ src/native/src/org/apache/hadoop/security/ src/test/core/org/apache/hadoop/security/

Modified: hadoop/common/branches/yahoo-merge/src/native/configure.ac
URL: http://svn.apache.org/viewvc/hadoop/common/branches/yahoo-merge/src/native/configure.ac?rev=1079119&r1=1079118&r2=1079119&view=diff
==============================================================================
--- hadoop/common/branches/yahoo-merge/src/native/configure.ac (original)
+++ hadoop/common/branches/yahoo-merge/src/native/configure.ac Tue Mar  8 04:37:08 2011
@@ -86,15 +86,16 @@ AC_SUBST([JNI_CPPFLAGS])
 dnl Check for zlib headers
 AC_CHECK_HEADERS([zlib.h zconf.h], AC_COMPUTE_NEEDED_DSO(z,HADOOP_ZLIB_LIBRARY), AC_MSG_ERROR(Zlib headers were not found... native-hadoop library needs zlib to build. Please install the requisite zlib development package.))
 
+dnl Check for headers needed by the native Group resolution implementation
+AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h], [], AC_MSG_ERROR(Some system headers not found... please ensure their presence on your platform.))
+
 # Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
 
 # Checks for library functions.
 AC_CHECK_FUNCS([memset])
 
-AC_CONFIG_FILES([Makefile
-                 src/org/apache/hadoop/io/compress/zlib/Makefile
-                 lib/Makefile])
+AC_CONFIG_FILES([Makefile])
 AC_OUTPUT
 
 #

Added: hadoop/common/branches/yahoo-merge/src/native/src/org/apache/hadoop/security/JniBasedUnixGroupsMapping.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/yahoo-merge/src/native/src/org/apache/hadoop/security/JniBasedUnixGroupsMapping.c?rev=1079119&view=auto
==============================================================================
--- hadoop/common/branches/yahoo-merge/src/native/src/org/apache/hadoop/security/JniBasedUnixGroupsMapping.c (added)
+++ hadoop/common/branches/yahoo-merge/src/native/src/org/apache/hadoop/security/JniBasedUnixGroupsMapping.c Tue Mar  8 04:37:08 2011
@@ -0,0 +1,117 @@
+/**
+ * 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.
+ */
+#include <jni.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <grp.h>
+#include <stdio.h>
+#include <pwd.h>
+#include <string.h>
+
+#include "org_apache_hadoop_security_JniBasedUnixGroupsMapping.h"
+#include "org_apache_hadoop.h"
+
+static jobjectArray emptyGroups = NULL;
+
+JNIEXPORT jobjectArray JNICALL 
+Java_org_apache_hadoop_security_JniBasedUnixGroupsMapping_getGroupForUser 
+(JNIEnv *env, jobject jobj, jstring juser) {
+  extern int getGroupIDList(const char *user, int *ngroups, gid_t **groups);
+  extern int getGroupDetails(gid_t group, char **grpBuf);
+
+  jobjectArray jgroups; 
+  int error = -1;
+
+  if (emptyGroups == NULL) {
+    jobjectArray lEmptyGroups = (jobjectArray)(*env)->NewObjectArray(env, 0,
+            (*env)->FindClass(env, "java/lang/String"), NULL);
+    if (lEmptyGroups == NULL) {
+      goto cleanup;
+    }
+    emptyGroups = (*env)->NewGlobalRef(env, lEmptyGroups);
+    if (emptyGroups == NULL) {
+      goto cleanup;
+    }
+  }
+  char *grpBuf = NULL;
+  const char *cuser = (*env)->GetStringUTFChars(env, juser, NULL);
+  if (cuser == NULL) {
+    goto cleanup;
+  }
+
+  /*Get the number of the groups, and their IDs, this user belongs to*/
+  gid_t *groups = NULL;
+  int ngroups = 0;
+  error = getGroupIDList(cuser, &ngroups, &groups);
+  if (error != 0) {
+    goto cleanup; 
+  }
+
+  jgroups = (jobjectArray)(*env)->NewObjectArray(env, ngroups, 
+            (*env)->FindClass(env, "java/lang/String"), NULL);
+  if (jgroups == NULL) {
+    error = -1;
+    goto cleanup; 
+  }
+
+  /*Iterate over the groupIDs and get the group structure for each*/
+  int i = 0;
+  for (i = 0; i < ngroups; i++) {
+    error = getGroupDetails(groups[i],&grpBuf);
+    if (error != 0) {
+      goto cleanup;
+    }
+    jstring jgrp = (*env)->NewStringUTF(env, ((struct group*)grpBuf)->gr_name);
+    if (jgrp == NULL) {
+      error = -1;
+      goto cleanup;
+    }
+    (*env)->SetObjectArrayElement(env, jgroups,i,jgrp);
+    free(grpBuf);
+    grpBuf = NULL;
+  }
+
+cleanup:
+  if (error == ENOMEM) {
+    THROW(env, "java/lang/OutOfMemoryError", NULL);
+  }
+  if (error == ENOENT) {
+    THROW(env, "java/io/IOException", "No entry for user");
+  }
+  if (groups != NULL) {
+    free(groups);
+  }
+  if (grpBuf != NULL) {
+    free(grpBuf);
+  }
+  if (cuser != NULL) {
+    (*env)->ReleaseStringUTFChars(env, juser, cuser);
+  }
+  if (error == 0) {
+    return jgroups;
+  } else {
+    return emptyGroups;
+  }
+}

Added: hadoop/common/branches/yahoo-merge/src/native/src/org/apache/hadoop/security/getGroup.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/yahoo-merge/src/native/src/org/apache/hadoop/security/getGroup.c?rev=1079119&view=auto
==============================================================================
--- hadoop/common/branches/yahoo-merge/src/native/src/org/apache/hadoop/security/getGroup.c (added)
+++ hadoop/common/branches/yahoo-merge/src/native/src/org/apache/hadoop/security/getGroup.c Tue Mar  8 04:37:08 2011
@@ -0,0 +1,189 @@
+/**
+ * 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.
+ */
+#include <grp.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+/*Helper functions for the JNI implementation of unix group mapping service*/
+
+
+/**
+ * Gets the group IDs for a given user. The groups argument is allocated
+ * internally, and it contains the list of groups. The ngroups is updated to 
+ * the number of groups
+ * Returns 0 on success (on success, the caller must free the memory allocated
+ * internally)
+ */
+int getGroupIDList(const char *user, int *ngroups, gid_t **groups) {
+  int getPW(const char *user, char **pwbuf);
+  *ngroups = 0;
+  char *pwbuf = NULL;
+  *groups = NULL;
+  /*Look up the password database first*/
+  int error = getPW(user, &pwbuf);
+  if (error != 0) {
+    if (pwbuf != NULL) {
+      free(pwbuf);
+    }
+    return error;
+  } 
+  struct passwd *pw = (struct passwd*)pwbuf;
+  int ng = 0;
+  /*Get the groupIDs that this user belongs to*/
+  if (getgrouplist(user, pw->pw_gid, NULL, &ng) < 0) {
+    *ngroups = ng;
+    *groups = (gid_t *) malloc(ng * sizeof (gid_t));
+    if (!*groups) {
+      *ngroups = 0;
+      free(pwbuf);
+      return ENOMEM;
+    }
+    if (getgrouplist(user, pw->pw_gid, *groups, &ng) < 0) {
+      *ngroups = 0;
+      free(pwbuf);
+      free(*groups);
+      *groups = NULL;
+      return ENOENT;
+    }
+  }
+  free(pwbuf);
+  return 0;
+}
+
+/**
+ * Gets the group structure for a given group ID. 
+ * The grpBuf argument is allocated internally and it contains the 
+ * struct group for the given group ID. 
+ * Returns 0 on success (on success, the caller must free the memory allocated
+ * internally)
+ */
+int getGroupDetails(gid_t group, char **grpBuf) {
+  struct group * grp = NULL;
+  size_t currBufferSize = sysconf(_SC_GETGR_R_SIZE_MAX);
+  if (currBufferSize < 1024) {
+    currBufferSize = 1024;
+  }
+  *grpBuf = NULL; 
+  char *buf = (char*)malloc(sizeof(char) * currBufferSize);
+
+  if (!buf) {
+    return ENOMEM;
+  }
+  int error;
+  for (;;) {
+    error = getgrgid_r(group, (struct group*)buf,
+                       buf + sizeof(struct group),
+                       currBufferSize - sizeof(struct group), &grp);
+    if(error != ERANGE) {
+       break;
+    }
+    free(buf);
+    currBufferSize *= 2;
+    buf = malloc(sizeof(char) * currBufferSize);
+    if(!buf) {
+      return ENOMEM;
+    }
+  }
+  if(!grp && !error) {
+    free(buf);
+    return ENOENT;
+  } else  if (error) {
+    free(buf);
+    return error;
+  }
+  *grpBuf = buf;
+  return 0;
+}
+
+/**
+ * Gets the password database entry for a given user. 
+ * The pwbuf argument is allocated internally and it contains the 
+ * broken out fields for the password database entry
+ * Returns 0 on success (on success, the caller must free the memory allocated 
+ * internally).
+ */
+int getPW(const char *user, char **pwbuf) {
+  struct passwd *pwbufp = NULL;
+  size_t currBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX);
+  if (currBufferSize < 1024) {
+    currBufferSize = 1024;
+  }
+  *pwbuf = NULL;
+  char *buf = (char*)malloc(sizeof(char) * currBufferSize);
+  
+  if (!buf) {
+    return ENOMEM;
+  } 
+  int error;
+  
+  for (;;) {
+    error = getpwnam_r(user, (struct passwd*)buf, buf + sizeof(struct passwd),
+                       currBufferSize - sizeof(struct passwd), &pwbufp);
+    if (error != ERANGE) {
+      break;
+    }
+    free(buf);
+    currBufferSize *= 2;
+    buf = (char*)malloc(sizeof(char) * currBufferSize);
+    if (!buf) {
+      return ENOMEM;
+    }
+  } 
+  if (!pwbufp && !error) {
+    free(buf);
+    return ENOENT;
+  } else  if (error) {
+    free(buf);
+    return error;
+  }
+  *pwbuf = buf;
+  return 0;
+} 
+
+#undef TESTING
+
+#ifdef TESTING
+/**
+ * A main() is provided so that quick testing of this
+ * library can be done. 
+ */
+int main(int argc, char **argv) {
+  int ngroups;
+  gid_t *groups = NULL;
+  char *user = "ddas";
+  if (argc == 2) user = argv[1];
+  int error = getGroupIDList(user, &ngroups, &groups);
+  if (error != 0) {
+    printf("Couldn't obtain grp for user %s", user);
+    return;
+  }
+  int i;
+  for (i = 0; i < ngroups; i++) {
+    char *grpbuf = NULL;
+    error = getGroupDetails(groups[i], &grpbuf);
+    printf("grps[%d]: %s ",i, ((struct group*)grpbuf)->gr_name);
+    free(grpbuf);
+  }
+  free(groups);
+  return 0;
+}
+#endif

Added: hadoop/common/branches/yahoo-merge/src/test/core/org/apache/hadoop/security/TestJNIGroupsMapping.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/yahoo-merge/src/test/core/org/apache/hadoop/security/TestJNIGroupsMapping.java?rev=1079119&view=auto
==============================================================================
--- hadoop/common/branches/yahoo-merge/src/test/core/org/apache/hadoop/security/TestJNIGroupsMapping.java (added)
+++ hadoop/common/branches/yahoo-merge/src/test/core/org/apache/hadoop/security/TestJNIGroupsMapping.java Tue Mar  8 04:37:08 2011
@@ -0,0 +1,76 @@
+/**
+ * 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.hadoop.security;
+import static org.junit.Assume.assumeTrue;
+import static org.junit.Assert.*;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.hadoop.fs.CommonConfigurationKeys;
+import org.apache.hadoop.security.GroupMappingServiceProvider;
+import org.apache.hadoop.security.JniBasedUnixGroupsMapping;
+import org.apache.hadoop.security.ShellBasedUnixGroupsMapping;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.util.NativeCodeLoader;
+import org.apache.hadoop.util.ReflectionUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+
+
+public class TestJNIGroupsMapping {
+  
+  @Before
+  public void isNativeCodeLoaded() {
+    assumeTrue(NativeCodeLoader.isNativeCodeLoaded());
+  }
+  
+  @Test
+  public void testJNIGroupsMapping() throws Exception {
+    //for the user running the test, check whether the 
+    //ShellBasedUnixGroupsMapping and the JniBasedUnixGroupsMapping
+    //return the same groups
+    String user = UserGroupInformation.getCurrentUser().getShortUserName();
+    testForUser(user);
+    //check for a dummy non-existent user (both the implementations should
+    //return an empty list
+    testForUser("fooBarBaz1234DoesNotExist");
+  }
+  private void testForUser(String user) throws Exception {
+    GroupMappingServiceProvider g = new ShellBasedUnixGroupsMapping();
+    List<String> shellBasedGroups = g.getGroups(user);
+    g = new JniBasedUnixGroupsMapping();
+    List<String> jniBasedGroups = g.getGroups(user);
+    
+    String[] shellBasedGroupsArray = shellBasedGroups.toArray(new String[0]);
+    Arrays.sort(shellBasedGroupsArray);
+    String[] jniBasedGroupsArray = jniBasedGroups.toArray(new String[0]);
+    Arrays.sort(jniBasedGroupsArray);
+    
+    if (!Arrays.equals(shellBasedGroupsArray, jniBasedGroupsArray)) {
+      fail("Groups returned by " + 
+          ShellBasedUnixGroupsMapping.class.getCanonicalName() + 
+          " and " +
+          JniBasedUnixGroupsMapping.class.getCanonicalName() + 
+          " didn't match for " + user);
+    }
+  }
+}