1/*
2 * Copyright (c) 2000, 2018, 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#include <jni.h>
27#include "jni_util.h"
28#include "com_sun_security_auth_module_UnixSystem.h"
29#include <stdio.h>
30#include <sys/types.h>
31#include <unistd.h>
32#include <stdlib.h>
33#include <string.h>
34
35/* For POSIX-compliant getpwuid_r on Solaris */
36#if defined(__solaris__)
37#define _POSIX_PTHREAD_SEMANTICS
38#endif
39#include <pwd.h>
40
41/*
42 * Declare library specific JNI_Onload entry if static build
43 */
44DEF_STATIC_JNI_OnLoad
45
46JNIEXPORT void JNICALL
47Java_com_sun_security_auth_module_UnixSystem_getUnixInfo
48 (JNIEnv *env, jobject obj) {
49
50 int i;
51 char pwd_buf[1024];
52 struct passwd *pwd;
53 struct passwd resbuf;
54 jfieldID userNameID;
55 jfieldID userID;
56 jfieldID groupID;
57 jfieldID supplementaryGroupID;
58
59 jstring jstr;
60 jlongArray jgroups;
61 jlong *jgroupsAsArray;
62 jsize numSuppGroups;
63 gid_t *groups;
64 jclass cls;
65
66 numSuppGroups = getgroups(0, NULL);
67 if (numSuppGroups == -1) {
68 return;
69 }
70 groups = (gid_t *)calloc(numSuppGroups, sizeof(gid_t));
71 if (groups == NULL) {
72 jclass cls = (*env)->FindClass(env,"java/lang/OutOfMemoryError");
73 if (cls != NULL)
74 (*env)->ThrowNew(env, cls, NULL);
75 return;
76 }
77
78 cls = (*env)->GetObjectClass(env, obj);
79
80 memset(pwd_buf, 0, sizeof(pwd_buf));
81
82 if (getpwuid_r(getuid(), &resbuf, pwd_buf, sizeof(pwd_buf), &pwd) == 0 &&
83 pwd != NULL &&
84 getgroups(numSuppGroups, groups) != -1) {
85
86 userNameID = (*env)->GetFieldID(env, cls, "username", "Ljava/lang/String;");
87 if (userNameID == 0)
88 goto cleanUpAndReturn;
89
90 userID = (*env)->GetFieldID(env, cls, "uid", "J");
91 if (userID == 0)
92 goto cleanUpAndReturn;
93
94 groupID = (*env)->GetFieldID(env, cls, "gid", "J");
95 if (groupID == 0)
96 goto cleanUpAndReturn;
97
98 supplementaryGroupID = (*env)->GetFieldID(env, cls, "groups", "[J");
99 if (supplementaryGroupID == 0)
100 goto cleanUpAndReturn;
101
102 jstr = (*env)->NewStringUTF(env, pwd->pw_name);
103 if (jstr == NULL)
104 goto cleanUpAndReturn;
105 (*env)->SetObjectField(env, obj, userNameID, jstr);
106
107 (*env)->SetLongField(env, obj, userID, pwd->pw_uid);
108
109 (*env)->SetLongField(env, obj, groupID, pwd->pw_gid);
110
111 jgroups = (*env)->NewLongArray(env, numSuppGroups);
112 if (jgroups == NULL)
113 goto cleanUpAndReturn;
114 jgroupsAsArray = (*env)->GetLongArrayElements(env, jgroups, 0);
115 if (jgroupsAsArray == NULL)
116 goto cleanUpAndReturn;
117 for (i = 0; i < numSuppGroups; i++)
118 jgroupsAsArray[i] = groups[i];
119 (*env)->ReleaseLongArrayElements(env, jgroups, jgroupsAsArray, 0);
120 (*env)->SetObjectField(env, obj, supplementaryGroupID, jgroups);
121 }
122cleanUpAndReturn:
123 free(groups);
124 return;
125}
126