1 /*
   2  * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #ifdef __solaris__
  27 #define _POSIX_C_SOURCE 199506L
  28 #endif
  29 
  30 #include <jni.h>
  31 #include "com_sun_security_auth_module_UnixSystem.h"
  32 #include <stdio.h>
  33 #include <pwd.h>
  34 #include <sys/types.h>
  35 #include <unistd.h>
  36 #include <stdlib.h>
  37 #include <string.h>
  38 
  39 JNIEXPORT void JNICALL
  40 Java_com_sun_security_auth_module_UnixSystem_getUnixInfo
  41                                                 (JNIEnv *env, jobject obj) {
  42 
  43     int i;
  44     char pwd_buf[1024];
  45     struct passwd *pwd;
  46     struct passwd resbuf;
  47     jfieldID userNameID;
  48     jfieldID userID;
  49     jfieldID groupID;
  50     jfieldID supplementaryGroupID;
  51 
  52     jstring jstr;
  53     jlongArray jgroups;
  54     jlong *jgroupsAsArray;
  55     jsize numSuppGroups;
  56     gid_t *groups;
  57     jclass cls;
  58 
  59     numSuppGroups = getgroups(0, NULL);
  60     groups = (gid_t *)calloc(numSuppGroups, sizeof(gid_t));
  61     if (groups == NULL) {
  62         jclass cls = (*env)->FindClass(env,"java/lang/OutOfMemoryError");
  63         if (cls != NULL)
  64             (*env)->ThrowNew(env, cls, NULL);
  65         return;
  66     }
  67 
  68     cls = (*env)->GetObjectClass(env, obj);
  69 
  70     memset(pwd_buf, 0, sizeof(pwd_buf));
  71 
  72     if (getpwuid_r(getuid(), &resbuf, pwd_buf, sizeof(pwd_buf), &pwd) == 0 &&
  73         pwd != NULL &&
  74         getgroups(numSuppGroups, groups) != -1) {
  75 
  76         userNameID = (*env)->GetFieldID(env, cls, "username", "Ljava/lang/String;");
  77         if (userNameID == 0)
  78             goto cleanUpAndReturn;
  79 
  80         userID = (*env)->GetFieldID(env, cls, "uid", "J");
  81         if (userID == 0)
  82             goto cleanUpAndReturn;
  83 
  84         groupID = (*env)->GetFieldID(env, cls, "gid", "J");
  85         if (groupID == 0)
  86             goto cleanUpAndReturn;
  87 
  88         supplementaryGroupID = (*env)->GetFieldID(env, cls, "groups", "[J");
  89         if (supplementaryGroupID == 0)
  90             goto cleanUpAndReturn;
  91 
  92         jstr = (*env)->NewStringUTF(env, pwd->pw_name);
  93         if (jstr == NULL)
  94             goto cleanUpAndReturn;
  95         (*env)->SetObjectField(env, obj, userNameID, jstr);
  96 
  97         (*env)->SetLongField(env, obj, userID, pwd->pw_uid);
  98 
  99         (*env)->SetLongField(env, obj, groupID, pwd->pw_gid);
 100 
 101         jgroups = (*env)->NewLongArray(env, numSuppGroups);
 102         if (jgroups == NULL)
 103             goto cleanUpAndReturn;
 104         jgroupsAsArray = (*env)->GetLongArrayElements(env, jgroups, 0);
 105         if (jgroupsAsArray == NULL)
 106             goto cleanUpAndReturn;
 107         for (i = 0; i < numSuppGroups; i++)
 108             jgroupsAsArray[i] = groups[i];
 109         (*env)->ReleaseLongArrayElements(env, jgroups, jgroupsAsArray, 0);
 110         (*env)->SetObjectField(env, obj, supplementaryGroupID, jgroups);
 111     }
 112 cleanUpAndReturn:
 113     free(groups);
 114     return;
 115 }