1/* 2 * Copyright (c) 2000, 2016, 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 "com_sun_security_auth_module_SolarisSystem.h" 28#include <stdio.h> 29#include <unistd.h> 30#include <stdlib.h> 31#include <string.h> 32 33/* For POSIX-compliant getpwuid_r on Solaris */ 34#if defined(__solaris__) 35#define _POSIX_PTHREAD_SEMANTICS 36#endif 37#include <pwd.h> 38 39static void throwIllegalArgumentException(JNIEnv *env, const char *msg) { 40 jclass clazz = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); 41 if (clazz != NULL) 42 (*env)->ThrowNew(env, clazz, msg); 43} 44 45JNIEXPORT void JNICALL 46Java_com_sun_security_auth_module_SolarisSystem_getSolarisInfo 47 (JNIEnv *env, jobject obj) { 48 49 int i; 50 long pwd_bufsize; 51 char *pwd_buf = NULL; 52 struct passwd pwd; 53 struct passwd* p = NULL; 54 jsize numSuppGroups = getgroups(0, NULL); 55 jfieldID fid; 56 jstring jstr; 57 jlongArray jgroups; 58 jlong *jgroupsAsArray; 59 gid_t *groups; 60 jclass cls; 61 62 pwd_bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); 63 if (pwd_bufsize == -1) { 64 pwd_bufsize = 1024; 65 } 66 pwd_buf = (char *)malloc(pwd_bufsize); 67 groups = (gid_t *)calloc(numSuppGroups, sizeof(gid_t)); 68 69 if (pwd_buf == NULL || groups == NULL) { 70 if (pwd_buf != NULL) { 71 free(pwd_buf); 72 } 73 if (groups != NULL) { 74 free(groups); 75 } 76 cls = (*env)->FindClass(env,"java/lang/OutOfMemoryError"); 77 if (cls != NULL) { 78 (*env)->ThrowNew(env, cls, NULL); 79 } 80 return; 81 } 82 83 cls = (*env)->GetObjectClass(env, obj); 84 85 if (getpwuid_r(getuid(), &pwd, pwd_buf, sizeof(pwd_buf), &p) != 0 && 86 p != NULL && getgroups(numSuppGroups, groups) != -1) { 87 88 /* 89 * set username 90 */ 91 fid = (*env)->GetFieldID(env, cls, "username", "Ljava/lang/String;"); 92 if (fid == 0) { 93 (*env)->ExceptionClear(env); 94 throwIllegalArgumentException(env, "invalid field: username"); 95 goto cleanupAndReturn; 96 } 97 jstr = (*env)->NewStringUTF(env, pwd.pw_name); 98 if (jstr == NULL) { 99 goto cleanupAndReturn; 100 } 101 (*env)->SetObjectField(env, obj, fid, jstr); 102 103 /* 104 * set uid 105 */ 106 fid = (*env)->GetFieldID(env, cls, "uid", "J"); 107 if (fid == 0) { 108 (*env)->ExceptionClear(env); 109 throwIllegalArgumentException(env, "invalid field: uid"); 110 goto cleanupAndReturn; 111 } 112 (*env)->SetLongField(env, obj, fid, pwd.pw_uid); 113 114 /* 115 * set gid 116 */ 117 fid = (*env)->GetFieldID(env, cls, "gid", "J"); 118 if (fid == 0) { 119 (*env)->ExceptionClear(env); 120 throwIllegalArgumentException(env, "invalid field: gid"); 121 goto cleanupAndReturn; 122 } 123 (*env)->SetLongField(env, obj, fid, pwd.pw_gid); 124 125 /* 126 * set supplementary groups 127 */ 128 fid = (*env)->GetFieldID(env, cls, "groups", "[J"); 129 if (fid == 0) { 130 (*env)->ExceptionClear(env); 131 throwIllegalArgumentException(env, "invalid field: groups"); 132 goto cleanupAndReturn; 133 } 134 135 jgroups = (*env)->NewLongArray(env, numSuppGroups); 136 if (jgroups == NULL) { 137 goto cleanupAndReturn; 138 } 139 jgroupsAsArray = (*env)->GetLongArrayElements(env, jgroups, 0); 140 if (jgroupsAsArray == NULL) { 141 goto cleanupAndReturn; 142 } 143 for (i = 0; i < numSuppGroups; i++) 144 jgroupsAsArray[i] = groups[i]; 145 (*env)->ReleaseLongArrayElements(env, jgroups, jgroupsAsArray, 0); 146 (*env)->SetObjectField(env, obj, fid, jgroups); 147 } 148cleanupAndReturn: 149 free(pwd_buf); 150 free(groups); 151 return; 152} 153