Author: mturk Date: Tue Sep 6 07:59:45 2011 New Revision: 1165549 URL: http://svn.apache.org/viewvc?rev=1165549&view=rev Log: Implement windows user and group classes
Added: commons/sandbox/runtime/trunk/src/main/native/os/win32/group.c (with props) commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfd.c (with props) commons/sandbox/runtime/trunk/src/main/native/os/win32/user.c (with props) Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in commons/sandbox/runtime/trunk/src/main/native/os/win32/arch_opts.h commons/sandbox/runtime/trunk/src/main/native/os/win32/security.c commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestUser.java Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in?rev=1165549&r1=1165548&r2=1165549&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in (original) +++ commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in Tue Sep 6 07:59:45 2011 @@ -81,6 +81,7 @@ WIN32_SOURCES=\ $(TOPDIR)\os\win32\dso.c \ $(TOPDIR)\os\win32\exec.c \ $(TOPDIR)\os\win32\execmem.c \ + $(TOPDIR)\os\win32\group.c \ $(TOPDIR)\os\win32\inetsock.c \ $(TOPDIR)\os\win32\init.c \ $(TOPDIR)\os\win32\ipcsock.c \ @@ -98,12 +99,14 @@ WIN32_SOURCES=\ $(TOPDIR)\os\win32\security.c \ $(TOPDIR)\os\win32\selectset.c \ $(TOPDIR)\os\win32\semaphore.c \ + $(TOPDIR)\os\win32\sendfd.c \ $(TOPDIR)\os\win32\sendfile.c \ $(TOPDIR)\os\win32\service.c \ $(TOPDIR)\os\win32\shmem.c \ $(TOPDIR)\os\win32\sockopts.c \ $(TOPDIR)\os\win32\sockstream.c \ $(TOPDIR)\os\win32\time.c \ + $(TOPDIR)\os\win32\user.c \ $(TOPDIR)\os\win32\util.c \ $(TOPDIR)\os\win32\winapi.c \ $(TOPDIR)\os\win32\wpipe.c Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/arch_opts.h URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/arch_opts.h?rev=1165549&r1=1165548&r2=1165549&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/arch_opts.h (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/arch_opts.h Tue Sep 6 07:59:45 2011 @@ -300,5 +300,11 @@ int symlink_w(const wchar_t * ssize_t readlink_w(const wchar_t *lnkname, wchar_t *buf, size_t len); PSECURITY_ATTRIBUTES GetSaWithNullDacl(JNI_STDENV, jboolean inherit); +PSID GetSidFromAccountName(LPCWSTR name, PSID_NAME_USE sidtype); +SID_NAME_USE GetAccountNameFromSid(LPWSTR buf, size_t blen, PSID psid); +SID_NAME_USE GetAccountSidType(PSID psid); +DWORD GetUserHomePath(LPWSTR buf, DWORD blen, PSID sid); +HANDLE GetCurrentAccessToken(JNI_STDENV); +LPVOID GetTokenInformationEx(JNI_STDENV, HANDLE h, TOKEN_INFORMATION_CLASS ic); #endif /* _ACR_ARCH_OPTS_H_ */ Added: commons/sandbox/runtime/trunk/src/main/native/os/win32/group.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/group.c?rev=1165549&view=auto ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/group.c (added) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/group.c Tue Sep 6 07:59:45 2011 @@ -0,0 +1,386 @@ +/* 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 "acr/string.h" +#include "acr/clazz.h" +#include "acr/jniapi.h" +#include "acr/port.h" +#include "acr/misc.h" +#include "acr/users.h" +#include "arch_opts.h" + +#include <lm.h> +#include <sddl.h> + +J_DECLARE_CLAZZ = { + INVALID_FIELD_OFFSET, + 0, + 0, + 0, + ACR_CLASS_PATH "Group" +}; + +J_DECLARE_M_ID(0000) = { + 0, + "<init>", + "(J[B)V" +}; + +J_DECLARE_F_ID(0000) = { + INVALID_FIELD_OFFSET, + INVALID_FIELD_OFFSET, + 0, + "Name", + "Ljava/lang/String;" +}; + +J_DECLARE_F_ID(0001) = { + INVALID_FIELD_OFFSET, + INVALID_FIELD_OFFSET, + 0, + "Comment", + "Ljava/lang/String;" +}; + +J_DECLARE_F_ID(0002) = { + INVALID_FIELD_OFFSET, + INVALID_FIELD_OFFSET, + 0, + "GroupId", + "Ljava/lang/String;" +}; + +J_DECLARE_F_ID(0003) = { + INVALID_FIELD_OFFSET, + INVALID_FIELD_OFFSET, + 0, + "isLocal", + "Z" +}; + +ACR_CLASS_CTOR(Group) +{ + if (AcrLoadClass(env, &_clazzn, 0) == JNI_FALSE) + return JNI_FALSE; + J_LOAD_METHOD(0000); + J_LOAD_IFIELD(0000); + J_LOAD_IFIELD(0001); + J_LOAD_IFIELD(0002); + J_LOAD_IFIELD(0003); + + _clazzn.u = 1; + return JNI_TRUE; +} + +ACR_CLASS_DTOR(Group) +{ + AcrUnloadClass(env, &_clazzn); +} + +jobjectArray AcrNewGroupArray(JNI_STDENV, jsize len) +{ + if (_clazzn.i) + return (*env)->NewObjectArray(env, len, _clazzn.i, 0); + else + return 0; +} + +ACR_JNI_EXPORT(int, Group, init0)(JNI_STDARGS) +{ + return SECURITY_MAX_SID_SIZE; +} + +static jobject +group_byname(JNI_STDARGS, const wchar_t *name) +{ + jobject grp; + DWORD rc; + PSID sid, gid; + LPWSTR ssid = 0; + SID_NAME_USE sidtype; + PLOCALGROUP_INFO_1 pb = 0; + + sid = GetSidFromAccountName(name, &sidtype); + if (sid == 0) { + ACR_THROW_SYS_ERRNO(); + return 0; + } + if (sidtype != SidTypeGroup && sidtype != SidTypeAlias && + sidtype != SidTypeWellKnownGroup) { + /* Not a group SID */ + ACR_THROW_SYS_ERROR(ACR_ENOENT); + AcrFree(sid); + return 0; + } + + if (obj == 0) + obj = (*env)->NewByteArray(env, SECURITY_MAX_SID_SIZE); + gid = (*env)->GetPrimitiveArrayCritical(env, obj, 0); + CopySid(SECURITY_MAX_SID_SIZE, gid, sid); + AcrFree(sid); + grp = (*env)->NewObject(env, _clazzn.i, J4MID(0000), P2J(gid), obj); + if (grp == 0) + return 0; + rc = NetLocalGroupGetInfo(0, name, 1, (LPBYTE *)&pb); + if (rc == NERR_GroupNotFound || rc == ERROR_NO_SUCH_ALIAS || + rc == ERROR_NO_SUCH_GROUP) + rc = NetGroupGetInfo(0, name, 1, (LPBYTE *)&pb); + if (rc == 0) { + SET_IFIELD_W(0000, grp, pb->lgrpi1_name); + SET_IFIELD_C(0001, grp, pb->lgrpi1_comment); + NetApiBufferFree(pb); + } + else { + SET_IFIELD_W(0000, grp, name); + } + if (ConvertSidToStringSidW(sid, &ssid)) { + SET_IFIELD_W(0002, grp, ssid); + LocalFree(ssid); + } + SET_IFIELD_Z(0003, grp, JNI_TRUE); + return grp; +} + +static jobject +group_fromgid(JNI_STDARGS, PSID sid) +{ + jobject grp; + DWORD rc; + PSID gid; + LPWSTR ssid = 0; + WCHAR name[MAX_PATH]; + SID_NAME_USE sidtype; + PLOCALGROUP_INFO_1 pb = 0; + + sidtype = GetAccountNameFromSid(name, MAX_PATH, sid); + if (sidtype == -1) { + ACR_THROW_SYS_ERRNO(); + return 0; + } + if (sidtype != SidTypeGroup && sidtype != SidTypeAlias && + sidtype != SidTypeWellKnownGroup) { + /* Not a group SID */ + ACR_THROW_SYS_ERROR(ACR_ENOENT); + return 0; + } + if (obj == 0) + obj = (*env)->NewByteArray(env, SECURITY_MAX_SID_SIZE); + gid = (*env)->GetPrimitiveArrayCritical(env, obj, 0); + CopySid(SECURITY_MAX_SID_SIZE, gid, sid); + grp = (*env)->NewObject(env, _clazzn.i, J4MID(0000), P2J(gid), obj); + if (grp == 0) { + return 0; + } + rc = NetLocalGroupGetInfo(0, name, 1, (LPBYTE *)&pb); + if (rc == NERR_GroupNotFound || rc == ERROR_NO_SUCH_ALIAS || + rc == ERROR_NO_SUCH_GROUP) + rc = NetGroupGetInfo(0, name, 1, (LPBYTE *)&pb); + if (rc == 0) { + SET_IFIELD_W(0000, grp, pb->lgrpi1_name); + SET_IFIELD_C(0001, grp, pb->lgrpi1_comment); + NetApiBufferFree(pb); + } + else { + SET_IFIELD_W(0000, grp, name); + } + if (ConvertSidToStringSidW(sid, &ssid)) { + SET_IFIELD_W(0002, grp, ssid); + LocalFree(ssid); + } + SET_IFIELD_Z(0003, grp, JNI_TRUE); + return grp; +} + +ACR_JNI_EXPORT(jboolean, Group, equals0)(JNI_STDARGS, jlong a, jlong b) +{ + PSID sa = J2P(a, PSID); + PSID sb = J2P(b, PSID); + if (a == 0) + return b == 0 ? JNI_TRUE : JNI_FALSE; + else + return EqualSid(sa, sb) ? JNI_TRUE : JNI_FALSE; +} + +ACR_JNI_EXPORT(jobject, Group, get0)(JNI_STDARGS, jstring name, + jbyteArray buf) +{ + jobject grp = 0; + WITH_WSTR(name) { + grp = group_byname(env, buf, J2S(name)); + } DONE_WITH_STR(name); + return grp; +} + +ACR_JNI_EXPORT(jobject, Group, get1)(JNI_STDARGS, jbyteArray buf) +{ + jobject gid = 0; + DWORD rc = 0; + HANDLE token; + PTOKEN_PRIMARY_GROUP grp = 0; + + if ((token = GetCurrentAccessToken(env)) == 0) + return 0; + grp = GetTokenInformationEx(env, token, TokenPrimaryGroup); + if (grp != 0) { + gid = group_fromgid(env, buf, grp->PrimaryGroup); + AcrFree(grp); + } + CloseHandle(token); + return gid; +} + +ACR_JNI_EXPORT(jobject, Group, get2)(JNI_STDARGS, jbyteArray buf) +{ + jobject gid = 0; + DWORD i, rc = 0; + HANDLE token; + SID_NAME_USE sidtype; + PTOKEN_GROUPS grp = NULL; + PTOKEN_OWNER own = NULL; + + if ((token = GetCurrentAccessToken(env)) == 0) + return 0; + own = GetTokenInformationEx(env, token, TokenOwner); + if (own != 0) { + sidtype = GetAccountSidType(own->Owner); + if (sidtype == SidTypeGroup || sidtype == SidTypeWellKnownGroup) + gid = group_fromgid(env, buf, own->Owner); + AcrFree(own); + } + if (gid == 0) { + grp = GetTokenInformationEx(env, token, TokenGroups); + if (grp == 0) + goto finally; + for (i = 0; i < grp->GroupCount; i++) { + if (grp->Groups[i].Attributes & SE_GROUP_OWNER) { + gid = group_fromgid(env, buf, grp->Groups[i].Sid); + break; + } + } + AcrFree(grp); + } +finally: + CloseHandle(token); + return gid; +} + +ACR_JNI_EXPORT(void, Group, enum0)(JNI_STDARGS, jobject ua) +{ + DWORD resumehandle = 0, total; + PGROUP_INFO_0 pb; + DWORD res, dwRec, n; + + do { + res = NetLocalGroupEnum(NULL, 0, (LPBYTE *)&pb, MAX_PREFERRED_LENGTH, + &dwRec, &total, (PDWORD_PTR)&resumehandle ); + if ((res == ERROR_SUCCESS) || (res == ERROR_MORE_DATA)) { + for (n = 0; n < dwRec; n++) { + jstring s; + s = AcrNewJavaStringW(env, pb[n].grpi0_name); + if (s == 0) { + NetApiBufferFree(pb); + return; + } + AcrArrayListAdd(env, ua, s); + if ((*env)->ExceptionCheck(env)) { + NetApiBufferFree(pb); + return; + } + (*env)->DeleteLocalRef(env, s); + } + NetApiBufferFree(pb); + } + } while (res == ERROR_MORE_DATA); + +} + +ACR_JNI_EXPORT(void, Group, enum1)(JNI_STDARGS, jobject ua) +{ + DWORD resumehandle = 0, total; + PGROUP_INFO_0 pb; + DWORD res, dwRec, n; + + do { + res = NetGroupEnum(NULL, 0, (LPBYTE *)&pb, MAX_PREFERRED_LENGTH, + &dwRec, &total, (PDWORD_PTR)&resumehandle ); + if ((res == ERROR_SUCCESS) || (res == ERROR_MORE_DATA)) { + for (n = 0; n < dwRec; n++) { + jstring s; + s = AcrNewJavaStringW(env, pb[n].grpi0_name); + if (s == 0) { + NetApiBufferFree(pb); + return; + } + AcrArrayListAdd(env, ua, s); + if ((*env)->ExceptionCheck(env)) { + NetApiBufferFree(pb); + return; + } + (*env)->DeleteLocalRef(env, s); + } + NetApiBufferFree(pb); + } + } while (res == ERROR_MORE_DATA); + +} + +ACR_JNI_EXPORT(void, Group, enum2)(JNI_STDARGS, jobject ua, jlong id) +{ + DWORD resumehandle = 0, total; + PLOCALGROUP_MEMBERS_INFO_1 pb; + DWORD res, dwRec, n; + PSID sid = J2P(id, PSID); + SID_NAME_USE sidtype; + WCHAR name[MAX_PATH]; + + sidtype = GetAccountNameFromSid(name, MAX_PATH, sid); + if (sidtype == -1) { + ACR_THROW_SYS_ERRNO(); + return; + } + if (sidtype != SidTypeGroup && sidtype != SidTypeAlias && + sidtype != SidTypeWellKnownGroup) { + /* Not a group SID */ + ACR_THROW_SYS_ERROR(ACR_ENOENT); + return; + } + do { + res = NetLocalGroupGetMembers(NULL, name, 1, (LPBYTE *)&pb, + MAX_PREFERRED_LENGTH, + &dwRec, &total, (PDWORD_PTR)&resumehandle ); + if ((res == ERROR_SUCCESS) || (res == ERROR_MORE_DATA)) { + for (n = 0; n < dwRec; n++) { + if (pb[n].lgrmi1_sidusage == SidTypeUser) { + /* Only count in the User accounts */ + jstring s; + s = AcrNewJavaStringW(env, pb[n].lgrmi1_name); + if (s == 0) { + NetApiBufferFree(pb); + return; + } + AcrArrayListAdd(env, ua, s); + if ((*env)->ExceptionCheck(env)) { + NetApiBufferFree(pb); + return; + } + (*env)->DeleteLocalRef(env, s); + } + } + NetApiBufferFree(pb); + } + } while (res == ERROR_MORE_DATA); + +} Propchange: commons/sandbox/runtime/trunk/src/main/native/os/win32/group.c ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/security.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/security.c?rev=1165549&r1=1165548&r2=1165549&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/security.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/security.c Tue Sep 6 07:59:45 2011 @@ -98,6 +98,150 @@ cleanup: return _null_SA[si]; } +PSID GetSidFromAccountName(LPCWSTR name, PSID_NAME_USE sidtype) +{ + WCHAR domain[MAX_PATH]; + DWORD domlen = MAX_PATH; + DWORD sidlen = 0; + PSID sid = NULL; + + *sidtype = -1; + LookupAccountNameW(NULL, name, NULL, &sidlen, + NULL, &domlen, sidtype); + if (sidlen != 0) { + /* Give it back on the second pass with proper sidlen + */ + if ((sid = malloc(sidlen)) == 0) { + ACR_SET_OS_ERROR(ACR_ENOMEM); + return 0; + } + domlen = MAX_PATH; + if (!LookupAccountNameW(NULL, name, sid, &sidlen, + domain, &domlen, sidtype)) { + free(sid); + sid = 0; + } + } + return sid; +} + +SID_NAME_USE GetAccountNameFromSid(LPWSTR buf, size_t blen, PSID psid) +{ + WCHAR domain[MAX_PATH]; + DWORD domlen = MAX_PATH; + DWORD acclen = (DWORD)blen; + SID_NAME_USE sidtype; + + if (!LookupAccountSidW(NULL, psid, + buf, &acclen, + domain, &domlen, + &sidtype)) { + + sidtype = -1; + buf[0] = L'\0'; + } + return sidtype; +} + +SID_NAME_USE GetAccountSidType(PSID psid) +{ + WCHAR domname[MAX_PATH]; + WCHAR accname[MAX_PATH]; + DWORD domlen = MAX_PATH; + DWORD acclen = MAX_PATH; + SID_NAME_USE sidtype; + + if (!LookupAccountSidW(NULL, psid, + accname, &acclen, + domname, &domlen, + &sidtype)) { + + sidtype = -1; + } + return sidtype; +} + +DWORD GetUserHomePath(LPWSTR buf, DWORD blen, PSID sid) +{ + LPWSTR ssid = NULL; + WCHAR regk[ACR_MBUFF_SIZ]; + HKEY key; + DWORD rv, type; + DWORD keylen; + + buf[0] = L'\0'; + + if (!ConvertSidToStringSidW(sid, &ssid)) + return GetLastError(); + wcscpy(regk, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"); + wcscat(regk, ssid); + LocalFree(ssid); + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, regk, 0, + KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) { + keylen = sizeof(regk); + rv = RegQueryValueExW(key, L"ProfileImagePath", NULL, &type, + (void *)regk, &keylen); + RegCloseKey(key); + if (rv != ERROR_SUCCESS) + return rv; + if (type == REG_SZ) + wcsncpy(buf, regk, blen); + else if (type == REG_EXPAND_SZ) + ExpandEnvironmentStringsW(regk, buf, blen); + buf[blen] = L'\0'; + } + return 0; +} + +HANDLE GetCurrentAccessToken(JNI_STDENV) +{ + HANDLE token = NULL; + DWORD rc; + + if (!OpenThreadToken(GetCurrentThread(), + TOKEN_QUERY | TOKEN_QUERY_SOURCE, + TRUE, &token)) { + if ((rc = GetLastError()) == ERROR_NO_TOKEN) { + if (!OpenProcessToken(GetCurrentProcess(), + TOKEN_QUERY | TOKEN_QUERY_SOURCE, + &token)) { + rc = GetLastError(); + } + else + rc = 0; + } + if (rc != ERROR_SUCCESS) { + ACR_THROW_SYS_ERROR(rc); + return 0; + } + } + return token; +} + +LPVOID GetTokenInformationEx(JNI_STDENV, HANDLE h, + TOKEN_INFORMATION_CLASS ic) +{ + LPVOID rv; + DWORD sz = 0; + DWORD rc; + + GetTokenInformation(h, ic, NULL, sz, &sz); + if ((rc = GetLastError()) != ERROR_INSUFFICIENT_BUFFER) { + ACR_THROW_SYS_ERROR(rc); + return 0; + } + if ((rv = ACR_MALLOC(char, sz)) == 0) { + return 0; + } + if (!GetTokenInformation(h, ic, rv, sz, &sz)) { + ACR_THROW_SYS_ERRNO(); + AcrFree(rv); + rv = 0; + } + return rv; +} + ACR_WIN_EXPORT(jlong, Security, GetCurrentProcessToken)(JNI_STDARGS) { HANDLE ptoken = 0; Added: commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfd.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfd.c?rev=1165549&view=auto ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfd.c (added) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfd.c Tue Sep 6 07:59:45 2011 @@ -0,0 +1,35 @@ +/* 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 "acr/jnitypes.h" +#include "acr/error.h" +#include "acr/debug.h" +#include "acr/memory.h" +#include "acr/netapi.h" +#include "acr/string.h" +#include "acr/port.h" +#include "arch_opts.h" +#include "arch_sync.h" + +#define MAX_SEND_FDS 512 + +ACR_NET_EXPORT(jstring, Utils, sendSocketName)(JNI_STDARGS, jint pid) +{ + char buf[32]; + snprintf(buf, sizeof(buf), "\\\\.\\pipe\\sendsock.%u", pid); + return AcrNewJavaStringA(env, buf); +} + Propchange: commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfd.c ------------------------------------------------------------------------------ svn:eol-style = native Added: commons/sandbox/runtime/trunk/src/main/native/os/win32/user.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/user.c?rev=1165549&view=auto ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/user.c (added) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/user.c Tue Sep 6 07:59:45 2011 @@ -0,0 +1,365 @@ +/* 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 "acr/string.h" +#include "acr/clazz.h" +#include "acr/jniapi.h" +#include "acr/port.h" +#include "acr/misc.h" +#include "acr/users.h" +#include "arch_opts.h" + +#include <lm.h> +#include <sddl.h> + +J_DECLARE_CLAZZ = { + INVALID_FIELD_OFFSET, + 0, + 0, + 0, + ACR_CLASS_PATH "User" +}; + +J_DECLARE_M_ID(0000) = { + 0, + "<init>", + "(J[B)V" +}; + +J_DECLARE_F_ID(0000) = { + INVALID_FIELD_OFFSET, + INVALID_FIELD_OFFSET, + 0, + "Name", + "Ljava/lang/String;" +}; + +J_DECLARE_F_ID(0001) = { + INVALID_FIELD_OFFSET, + INVALID_FIELD_OFFSET, + 0, + "FullName", + "Ljava/lang/String;" +}; + +J_DECLARE_F_ID(0002) = { + INVALID_FIELD_OFFSET, + INVALID_FIELD_OFFSET, + 0, + "Comment", + "Ljava/lang/String;" +}; + +J_DECLARE_F_ID(0003) = { + INVALID_FIELD_OFFSET, + INVALID_FIELD_OFFSET, + 0, + "Home", + "Ljava/lang/String;" +}; + +J_DECLARE_F_ID(0004) = { + INVALID_FIELD_OFFSET, + INVALID_FIELD_OFFSET, + 0, + "Shell", + "Ljava/lang/String;" +}; + +J_DECLARE_F_ID(0005) = { + INVALID_FIELD_OFFSET, + INVALID_FIELD_OFFSET, + 0, + "UserId", + "Ljava/lang/String;" +}; + +ACR_CLASS_CTOR(User) +{ + if (AcrLoadClass(env, &_clazzn, 0) == JNI_FALSE) + return JNI_FALSE; + J_LOAD_METHOD(0000); + J_LOAD_IFIELD(0000); + J_LOAD_IFIELD(0001); + J_LOAD_IFIELD(0002); + J_LOAD_IFIELD(0003); + J_LOAD_IFIELD(0004); + J_LOAD_IFIELD(0005); + + _clazzn.u = 1; + return JNI_TRUE; +} + +ACR_CLASS_DTOR(User) +{ + AcrUnloadClass(env, &_clazzn); +} + +jobjectArray AcrNewUserArray(JNI_STDENV, jsize len) +{ + if (_clazzn.i) + return (*env)->NewObjectArray(env, len, _clazzn.i, NULL); + else + return 0; +} + +ACR_JNI_EXPORT(int, User, init0)(JNI_STDARGS) +{ + return SECURITY_MAX_SID_SIZE; +} + +ACR_JNI_EXPORT(jboolean, User, equals0)(JNI_STDARGS, jlong a, jlong b) +{ + PSID sa = J2P(a, PSID); + PSID sb = J2P(b, PSID); + if (a == 0) + return b == 0 ? JNI_TRUE : JNI_FALSE; + else + return EqualSid(sa, sb) ? JNI_TRUE : JNI_FALSE; +} + +static jobject +user_byname(JNI_STDARGS, const wchar_t *name) +{ + jobject usr; + DWORD rc; + PSID sid, uid; + LPWSTR ssid = 0; + SID_NAME_USE sidtype; + PUSER_INFO_2 pb = 0; + WCHAR home[MAX_PATH+1]; + + sid = GetSidFromAccountName(name, &sidtype); + if (sid == 0) { + ACR_THROW_SYS_ERRNO(); + return 0; + } + if (sidtype != SidTypeUser && sidtype != SidTypeAlias) { + /* Not a group SID */ + ACR_THROW_SYS_ERROR(ACR_ENOENT); + AcrFree(sid); + return 0; + } + + if (obj == 0) + obj = (*env)->NewByteArray(env, SECURITY_MAX_SID_SIZE); + uid = (*env)->GetPrimitiveArrayCritical(env, obj, 0); + CopySid(SECURITY_MAX_SID_SIZE, uid, sid); + AcrFree(sid); + usr = (*env)->NewObject(env, _clazzn.i, J4MID(0000), P2J(uid), obj); + if (usr == 0) + return 0; + rc = NetUserGetInfo(NULL, name, 2, (LPBYTE *)&pb); + if (rc == 0) { + SET_IFIELD_W(0000, usr, pb->usri2_name); + SET_IFIELD_C(0001, usr, pb->usri2_full_name); + SET_IFIELD_C(0002, usr, pb->usri2_comment); + if (pb->usri2_home_dir && *pb->usri2_home_dir) + SET_IFIELD_W(0003, usr, pb->usri2_home_dir); + else { + GetUserHomePath(home, MAX_PATH, uid); + SET_IFIELD_C(0003, usr, home); + } + NetApiBufferFree(pb); + } + else if (rc == NERR_UserNotFound || rc == ERROR_NO_SUCH_ALIAS || + rc == ERROR_NO_SUCH_USER) { + SET_IFIELD_W(0000, usr, name); + SET_IFIELD_W(0001, usr, name); + GetUserHomePath(home, MAX_PATH, uid); + SET_IFIELD_C(0003, usr, home); + } + else { + ACR_THROW_SYS_ERROR(rc); + return 0; + } + if (ConvertSidToStringSidW(uid, &ssid)) { + SET_IFIELD_W(0005, usr, ssid); + LocalFree(ssid); + } + return usr; +} + +static jobject +user_fromuid(JNI_STDARGS, PSID sid) +{ + jobject usr; + DWORD rc; + PSID uid; + LPWSTR ssid = 0; + WCHAR name[MAX_PATH]; + WCHAR home[MAX_PATH+1]; + SID_NAME_USE sidtype; + PUSER_INFO_2 pb = 0; + + sidtype = GetAccountNameFromSid(name, MAX_PATH, sid); + if (sidtype == -1) { + ACR_THROW_SYS_ERRNO(); + return 0; + } + if (sidtype != SidTypeUser && sidtype != SidTypeAlias) { + /* Not a group SID */ + ACR_THROW_SYS_ERROR(ACR_ENOENT); + return 0; + } + if (obj == 0) + obj = (*env)->NewByteArray(env, SECURITY_MAX_SID_SIZE); + uid = (*env)->GetPrimitiveArrayCritical(env, obj, 0); + CopySid(SECURITY_MAX_SID_SIZE, uid, sid); + usr = (*env)->NewObject(env, _clazzn.i, J4MID(0000), P2J(uid), obj); + if (usr == 0) { + return 0; + } + rc = NetUserGetInfo(NULL, name, 2, (LPBYTE *)&pb); + if (rc == 0) { + SET_IFIELD_W(0000, usr, pb->usri2_name); + SET_IFIELD_C(0001, usr, pb->usri2_full_name); + SET_IFIELD_C(0002, usr, pb->usri2_comment); + if (pb->usri2_home_dir && *pb->usri2_home_dir) + SET_IFIELD_W(0003, usr, pb->usri2_home_dir); + else { + GetUserHomePath(home, MAX_PATH, uid); + SET_IFIELD_C(0003, usr, home); + } + NetApiBufferFree(pb); + } + else if (rc == NERR_UserNotFound || rc == ERROR_NO_SUCH_ALIAS || + rc == ERROR_NO_SUCH_USER) { + SET_IFIELD_W(0000, usr, name); + SET_IFIELD_W(0001, usr, name); + GetUserHomePath(home, MAX_PATH, uid); + SET_IFIELD_C(0003, usr, home); + } + else { + ACR_THROW_SYS_ERROR(rc); + return 0; + } + if (ConvertSidToStringSidW(uid, &ssid)) { + SET_IFIELD_W(0005, usr, ssid); + LocalFree(ssid); + } + return usr; +} + +ACR_JNI_EXPORT(jobject, User, get0)(JNI_STDARGS, jstring name, + jbyteArray buf) +{ + jobject usr = 0; + WITH_WSTR(name) { + usr = user_byname(env, buf, J2S(name)); + } DONE_WITH_STR(name); + return usr; +} + +ACR_JNI_EXPORT(jobject, User, get1)(JNI_STDARGS, jbyteArray buf) +{ + jobject uid = 0; + DWORD rc = 0; + HANDLE token; + PTOKEN_USER usr = 0; + + if ((token = GetCurrentAccessToken(env)) == 0) + return 0; + usr = GetTokenInformationEx(env, token, TokenUser); + if (usr != 0) { + uid = user_fromuid(env, buf, usr->User.Sid); + AcrFree(usr); + } + CloseHandle(token); + return uid; +} + +ACR_JNI_EXPORT(jobject, User, get2)(JNI_STDARGS, jbyteArray buf) +{ + jobject uid = 0; + DWORD rc = 0; + HANDLE token; + PTOKEN_OWNER usr = 0; + + if ((token = GetCurrentAccessToken(env)) == 0) + return 0; + usr = GetTokenInformationEx(env, token, TokenOwner); + if (usr != 0) { + SID_NAME_USE sidtype = GetAccountSidType(usr->Owner); + if (sidtype == SidTypeUser) + uid = user_fromuid(env, buf, usr->Owner); + AcrFree(usr); + } + CloseHandle(token); + return uid; +} + +ACR_JNI_EXPORT(void, User, enum0)(JNI_STDARGS, jobject ua) +{ + DWORD resumehandle = 0, total; + PUSER_INFO_0 pb; + DWORD res, dwRec, n; + + do { + res = NetUserEnum(0, 0, 0, (LPBYTE *)&pb, MAX_PREFERRED_LENGTH, + &dwRec, &total, (LPDWORD)&resumehandle); + if ((res == ERROR_SUCCESS) || (res == ERROR_MORE_DATA)) { + for (n = 0; n < dwRec; n++) { + jstring s; + s = AcrNewJavaStringW(env, pb[n].usri0_name); + if (s == 0) { + NetApiBufferFree(pb); + return; + } + AcrArrayListAdd(env, ua, s); + if ((*env)->ExceptionCheck(env)) { + NetApiBufferFree(pb); + return; + } + (*env)->DeleteLocalRef(env, s); + } + NetApiBufferFree(pb); + } + } while (res == ERROR_MORE_DATA); + +} + +ACR_JNI_EXPORT(void, User, enum1)(JNI_STDARGS, jobject ua) +{ + DWORD resumehandle = 0, total; + PWKSTA_USER_INFO_0 pb; + DWORD res, dwRec, n; + + do { + res = NetWkstaUserEnum(0, 0, (LPBYTE *)&pb, MAX_PREFERRED_LENGTH, + &dwRec, &total, (LPDWORD)&resumehandle); + if ((res == ERROR_SUCCESS) || (res == ERROR_MORE_DATA)) { + for (n = 0; n < dwRec; n++) { + jstring s; + if (wcschr(pb[n].wkui0_username, L'$')) + continue; + s = AcrNewJavaStringW(env, pb[n].wkui0_username); + if (s == 0) { + NetApiBufferFree(pb); + return; + } + AcrArrayListAdd(env, ua, s); + if ((*env)->ExceptionCheck(env)) { + NetApiBufferFree(pb); + return; + } + (*env)->DeleteLocalRef(env, s); + } + NetApiBufferFree(pb); + } + } while (res == ERROR_MORE_DATA); + +} Propchange: commons/sandbox/runtime/trunk/src/main/native/os/win32/user.c ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestUser.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestUser.java?rev=1165549&r1=1165548&r2=1165549&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestUser.java (original) +++ commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestUser.java Tue Sep 6 07:59:45 2011 @@ -23,13 +23,20 @@ import java.lang.reflect.*; public class TestUser extends Assert { - @Test(groups = { "core" }) + @Test(groups = { "posix" }) public void checkRoot() { User u = User.get("root"); assertNotNull(u); } + @Test(groups = { "windows" }) + public void checkAdmin() + { + User u = User.get("Guest"); + assertNotNull(u); + } + @Test(groups = { "core" }) public void getUsers() {