1 /*
2 * Copyright (c) 2011, 2019, 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 #import <Cocoa/Cocoa.h>
27 #import <JavaNativeFoundation/JavaNativeFoundation.h>
28 #import <SystemConfiguration/SystemConfiguration.h>
29
30
31 @interface JNFVectorCoercion : NSObject <JNFTypeCoercion> { }
32 @end
33
34 @implementation JNFVectorCoercion
35
36 - (jobject) coerceNSObject:(id)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer {
37 static JNF_CLASS_CACHE(jc_Vector, "java/util/Vector");
38 static JNF_CTOR_CACHE(jm_Vector_ctor, jc_Vector, "(I)V");
39 static JNF_MEMBER_CACHE(jm_Vector_add, jc_Vector, "add", "(Ljava/lang/Object;)Z");
40
41 NSArray *nsArray = (NSArray *)obj;
42 jobject javaArray = JNFNewObject(env, jm_Vector_ctor, (jint)[nsArray count]);
43
44 for (id obj in nsArray) {
45 jobject jobj = [coercer coerceNSObject:obj withEnv:env usingCoercer:coercer];
46 JNFCallBooleanMethod(env, javaArray, jm_Vector_add, jobj);
47 if (jobj != NULL) (*env)->DeleteLocalRef(env, jobj);
48 }
49
50 return javaArray;
51 }
52
53 - (id) coerceJavaObject:(jobject)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer {
54 return nil;
55 }
56
57 @end
58
59
60 @interface JNFHashtableCoercion : NSObject <JNFTypeCoercion> { }
61 @end
62
63 @implementation JNFHashtableCoercion
64
65 - (jobject) coerceNSObject:(id)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer {
66 static JNF_CLASS_CACHE(jc_Hashtable, "java/util/Hashtable");
67 static JNF_CTOR_CACHE(jm_Hashtable_ctor, jc_Hashtable, "()V");
68 static JNF_MEMBER_CACHE(jm_Hashtable_put, jc_Hashtable, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
69
70 NSDictionary *nsDict = (NSDictionary *)obj;
71 NSEnumerator *keyEnum = [nsDict keyEnumerator];
72
73 jobject jHashTable = JNFNewObject(env, jm_Hashtable_ctor);
74
75 id key = nil;
76 while ((key = [keyEnum nextObject]) != nil) {
77 jobject jkey = [coercer coerceNSObject:key withEnv:env usingCoercer:coercer];
78
79 id value = [nsDict objectForKey:key];
80 jobject jvalue = [coercer coerceNSObject:value withEnv:env usingCoercer:coercer];
81
82 JNFCallObjectMethod(env, jHashTable, jm_Hashtable_put, jkey, jvalue);
83
84 if (jkey != NULL) (*env)->DeleteLocalRef(env, jkey);
85 if (jvalue != NULL) (*env)->DeleteLocalRef(env, jvalue);
86 }
87
88 return jHashTable;
89 }
90
91 - (id) coerceJavaObject:(jobject)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer {
92 return nil;
93 }
94
95 @end
96
97
98
99 NSDictionary *realmConfigsForRealms(SCDynamicStoreRef store, NSArray *realms) {
100 NSMutableDictionary *dict = [NSMutableDictionary dictionary];
101
102 for (NSString *realm in realms) {
103 CFTypeRef realmInfo = SCDynamicStoreCopyValue(store, (CFStringRef) [NSString stringWithFormat:@"Kerberos:%@", realm]);
104
105 if (realmInfo == NULL || CFGetTypeID(realmInfo) != CFDictionaryGetTypeID()) {
106 if (realmInfo) CFRelease(realmInfo);
107 return nil;
108 }
109
110 [dict setObject:(NSArray *)realmInfo forKey:realm];
111 CFRelease(realmInfo);
112 }
113
114 return dict;
115 }
116
117
118 #define KERBEROS_DEFAULT_REALMS @"Kerberos-Default-Realms"
119 #define KERBEROS_DEFAULT_REALM_MAPPINGS @"Kerberos-Domain-Realm-Mappings"
120
121 void _SCDynamicStoreCallBack(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) {
122 NSArray *keys = (NSArray *)changedKeys;
123 if ([keys count] == 0) return;
124 if (![keys containsObject:KERBEROS_DEFAULT_REALMS] && ![keys containsObject:KERBEROS_DEFAULT_REALM_MAPPINGS]) return;
125
126 JNFPerformEnvBlock(JNFThreadDetachOnThreadDeath | JNFThreadSetSystemClassLoaderOnAttach | JNFThreadAttachAsDaemon, ^(JNIEnv *env) {
127 static JNF_CLASS_CACHE(jc_Config, "sun/security/krb5/Config");
128 static JNF_STATIC_MEMBER_CACHE(jm_Config_refresh, jc_Config, "refresh", "()V");
129 JNFCallStaticVoidMethod(env, jm_Config_refresh);
130 });
131 }
132
133 /*
134 * Class: sun_security_krb5_SCDynamicStoreConfig
135 * Method: installNotificationCallback
136 */
137 JNIEXPORT void JNICALL Java_sun_security_krb5_SCDynamicStoreConfig_installNotificationCallback(JNIEnv *env, jclass klass) {
138
139 JNF_COCOA_ENTER(env);
140
141 SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("java"), _SCDynamicStoreCallBack, NULL);
142 if (store == NULL) {
143 return;
144 }
145
146 NSArray *keys = [NSArray arrayWithObjects:KERBEROS_DEFAULT_REALMS, KERBEROS_DEFAULT_REALM_MAPPINGS, nil];
147 SCDynamicStoreSetNotificationKeys(store, (CFArrayRef) keys, NULL);
148
149 CFRunLoopSourceRef rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
150 if (rls != NULL) {
151 CFRunLoopAddSource(CFRunLoopGetMain(), rls, kCFRunLoopDefaultMode);
152 CFRelease(rls);
153 }
154
155 CFRelease(store);
156
157 JNF_COCOA_EXIT(env);
158
159 }
160
161 /*
162 * Class: sun_security_krb5_SCDynamicStoreConfig
163 * Method: getKerberosConfig
164 * Signature: ()Ljava/util/Hashtable;
165 */
166 JNIEXPORT jobject JNICALL Java_sun_security_krb5_SCDynamicStoreConfig_getKerberosConfig(JNIEnv *env, jclass klass) {
167 jobject jHashTable = NULL;
168
169 JNF_COCOA_ENTER(env);
170
171 SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("java-kerberos"), NULL, NULL);
172 if (store == NULL) {
173 return NULL;
174 }
175
176 CFTypeRef realms = SCDynamicStoreCopyValue(store, (CFStringRef) KERBEROS_DEFAULT_REALMS);
177 if (realms == NULL || CFGetTypeID(realms) != CFArrayGetTypeID()) {
178 if (realms) CFRelease(realms);
179 CFRelease(store);
180 return NULL;
181 }
182
183 CFTypeRef realmMappings = SCDynamicStoreCopyValue(store, (CFStringRef) KERBEROS_DEFAULT_REALM_MAPPINGS);
184
185 if (realmMappings == NULL || CFGetTypeID(realmMappings) != CFArrayGetTypeID()) {
186 if (realmMappings) CFRelease(realmMappings);
187 CFRelease(realms);
188 CFRelease(store);
189 return NULL;
190 }
191
192 NSMutableDictionary *dict = [NSMutableDictionary dictionary];
193
194 if (CFArrayGetCount(realms) > 0) {
195 NSDictionary *defaultRealmsDict = [NSDictionary dictionaryWithObject:[(NSArray *)realms objectAtIndex:0] forKey:@"default_realm"];
196 [dict setObject:defaultRealmsDict forKey:@"libdefaults"];
197
198 NSDictionary *realmConfigs = realmConfigsForRealms(store, (NSArray *)realms);
199 [dict setObject:realmConfigs forKey:@"realms"];
200 }
201 CFRelease(realms);
202 CFRelease(store);
203
204 if (CFArrayGetCount(realmMappings) > 0) {
205 [dict setObject:[(NSArray *)realmMappings objectAtIndex:0] forKey:@"domain_realm"];
206 }
207 CFRelease(realmMappings);
208
209
210 // create and load a coercer with all of the different coercions to convert each type of object
211 JNFTypeCoercer *coercer = [[[JNFTypeCoercer alloc] init] autorelease];
212 [JNFDefaultCoercions addStringCoercionTo:coercer];
213 [JNFDefaultCoercions addNumberCoercionTo:coercer];
214 [coercer addCoercion:[[[JNFHashtableCoercion alloc] init] autorelease] forNSClass:[NSDictionary class] javaClass:@"java/util/Map"];
215 [coercer addCoercion:[[[JNFVectorCoercion alloc] init] autorelease] forNSClass:[NSArray class] javaClass:@"java/util/List"];
216
217 // convert Cocoa graph to Java graph
218 jHashTable = [coercer coerceNSObject:dict withEnv:env];
219
220 JNF_COCOA_EXIT(env);
221
222 return jHashTable;
223 }
|
1 /*
2 * Copyright (c) 2011, 2021, 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 #import <Cocoa/Cocoa.h>
27 #import <SystemConfiguration/SystemConfiguration.h>
28 #import "jni_util.h"
29
30 #define KERBEROS_DEFAULT_REALMS @"Kerberos-Default-Realms"
31 #define KERBEROS_DEFAULT_REALM_MAPPINGS @"Kerberos-Domain-Realm-Mappings"
32 #define KERBEROS_REALM_INFO @"Kerberos:%@"
33
34 JavaVM *localVM;
35
36 void _SCDynamicStoreCallBack(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) {
37 NSArray *keys = (NSArray *)changedKeys;
38 if ([keys count] == 0) return;
39 if (![keys containsObject:KERBEROS_DEFAULT_REALMS] && ![keys containsObject:KERBEROS_DEFAULT_REALM_MAPPINGS]) return;
40
41 JNIEnv *env;
42 bool createdFromAttach = FALSE;
43 jint status = (*localVM)->GetEnv(localVM, (void**)&env, JNI_VERSION_1_2);
44 if (status == JNI_EDETACHED) {
45 status = (*localVM)->AttachCurrentThreadAsDaemon(localVM, (void**)&env, NULL);
46 createdFromAttach = TRUE;
47 }
48 if (status == 0) {
49 jclass jc_Config = (*env)->FindClass(env, "sun/security/krb5/Config");
50 CHECK_NULL(jc_Config);
51 jmethodID jm_Config_refresh = (*env)->GetStaticMethodID(env, jc_Config, "refresh", "()V");
52 CHECK_NULL(jm_Config_refresh);
53 (*env)->CallStaticVoidMethod(env, jc_Config, jm_Config_refresh);
54 if ((*env)->ExceptionOccurred(env) != NULL) {
55 (*env)->ExceptionClear(env);
56 }
57 if (createdFromAttach) {
58 (*localVM)->DetachCurrentThread(localVM);
59 }
60 }
61 }
62
63 /*
64 * Class: sun_security_krb5_SCDynamicStoreConfig
65 * Method: installNotificationCallback
66 */
67 JNIEXPORT void JNICALL Java_sun_security_krb5_SCDynamicStoreConfig_installNotificationCallback(JNIEnv *env, jclass klass) {
68 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; \
69 @try {
70 (*env)->GetJavaVM(env, &localVM);
71 SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("java"), _SCDynamicStoreCallBack, NULL);
72 if (store == NULL) {
73 return;
74 }
75
76 NSArray *keys = [NSArray arrayWithObjects:KERBEROS_DEFAULT_REALMS, KERBEROS_DEFAULT_REALM_MAPPINGS, nil];
77 SCDynamicStoreSetNotificationKeys(store, (CFArrayRef) keys, NULL);
78
79 CFRunLoopSourceRef rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
80 if (rls != NULL) {
81 CFRunLoopAddSource(CFRunLoopGetMain(), rls, kCFRunLoopDefaultMode);
82 CFRelease(rls);
83 }
84
85 CFRelease(store);
86 } @catch (NSException *e) {
87 NSLog(@"%@", [e callStackSymbols]);
88 } @finally {
89 [pool drain];
90 }
91 }
92
93 #define ADD(list, str) { \
94 jobject localeObj = (*env)->NewStringUTF(env, [str UTF8String]); \
95 (*env)->CallBooleanMethod(env, list, jm_listAdd, localeObj); \
96 (*env)->DeleteLocalRef(env, localeObj); \
97 }
98
99 #define ADDNULL(list) (*env)->CallBooleanMethod(env, list, jm_listAdd, NULL)
100
101 /*
102 * Class: sun_security_krb5_SCDynamicStoreConfig
103 * Method: getKerberosConfig
104 * Signature: ()Ljava/util/List;
105 */
106 JNIEXPORT jobject JNICALL Java_sun_security_krb5_SCDynamicStoreConfig_getKerberosConfig(JNIEnv *env, jclass klass) {
107
108 jobject newList = 0;
109
110 SCDynamicStoreRef store = NULL;
111 CFTypeRef realms = NULL;
112 CFTypeRef realmMappings = NULL;
113 CFTypeRef realmInfo = NULL;
114
115 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; \
116 @try {
117 SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("java-kerberos"), NULL, NULL);
118 if (store == NULL) {
119 return NULL;
120 }
121
122 CFTypeRef realms = SCDynamicStoreCopyValue(store, (CFStringRef) KERBEROS_DEFAULT_REALMS);
123 if (realms == NULL || CFGetTypeID(realms) != CFArrayGetTypeID()) {
124 return NULL;
125 }
126
127 // This methods returns a ArrayList<String>:
128 // (realm kdc* null) null (mapping-domain mapping-realm)*
129 jclass jc_arrayListClass = (*env)->FindClass(env, "java/util/ArrayList");
130 CHECK_NULL_RETURN(jc_arrayListClass, NULL);
131 jmethodID jm_arrayListCons = (*env)->GetMethodID(env, jc_arrayListClass, "<init>", "()V");
132 CHECK_NULL_RETURN(jm_arrayListCons, NULL);
133 jmethodID jm_listAdd = (*env)->GetMethodID(env, jc_arrayListClass, "add", "(Ljava/lang/Object;)Z");
134 CHECK_NULL_RETURN(jm_listAdd, NULL);
135 newList = (*env)->NewObject(env, jc_arrayListClass, jm_arrayListCons);
136 CHECK_NULL_RETURN(newList, NULL);
137
138 for (NSString *realm in (NSArray*)realms) {
139 if (realmInfo) CFRelease(realmInfo); // for the previous realm
140 realmInfo = SCDynamicStoreCopyValue(store, (CFStringRef) [NSString stringWithFormat:KERBEROS_REALM_INFO, realm]);
141 if (realmInfo == NULL || CFGetTypeID(realmInfo) != CFDictionaryGetTypeID()) {
142 continue;
143 }
144
145 ADD(newList, realm);
146 NSDictionary* ri = (NSDictionary*)realmInfo;
147 for (NSDictionary* k in (NSArray*)ri[@"kdc"]) {
148 ADD(newList, k[@"host"]);
149 }
150 ADDNULL(newList);
151 }
152 ADDNULL(newList);
153
154 CFTypeRef realmMappings = SCDynamicStoreCopyValue(store, (CFStringRef) KERBEROS_DEFAULT_REALM_MAPPINGS);
155 if (realmMappings != NULL && CFGetTypeID(realmMappings) == CFArrayGetTypeID()) {
156 for (NSDictionary* d in (NSArray *)realmMappings) {
157 for (NSString* s in d) {
158 ADD(newList, s);
159 ADD(newList, d[s]);
160 }
161 }
162 }
163 } @catch (NSException *e) {
164 NSLog(@"%@", [e callStackSymbols]);
165 } @finally {
166 [pool drain];
167 if (realmInfo) CFRelease(realmInfo);
168 if (realmMappings) CFRelease(realmMappings);
169 if (realms) CFRelease(realms);
170 if (store) CFRelease(store);
171 }
172 return newList;
173 }
|