Skip to content

Commit a61b441

Browse files
Yuri NesterenkoRealCLanger
authored andcommitted
8278972: Improve URL supports
Backport-of: 94f1fbfd6d23f18ade3cc1b36f6dd368963c9d02
1 parent 463ce03 commit a61b441

File tree

5 files changed

+648
-73
lines changed

5 files changed

+648
-73
lines changed

src/java.naming/share/classes/com/sun/jndi/ldap/LdapURL.java

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1999, 2002, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,10 @@
2828
import javax.naming.*;
2929
import java.net.MalformedURLException;
3030
import java.io.UnsupportedEncodingException;
31+
import java.net.URI;
32+
import java.security.AccessController;
33+
import java.security.PrivilegedAction;
34+
import java.util.Locale;
3135
import java.util.StringTokenizer;
3236
import com.sun.jndi.toolkit.url.Uri;
3337
import com.sun.jndi.toolkit.url.UrlUtil;
@@ -64,6 +68,25 @@
6468

6569
public final class LdapURL extends Uri {
6670

71+
private static final String PARSE_MODE_PROP = "com.sun.jndi.ldapURLParsing";
72+
private static final ParseMode DEFAULT_PARSE_MODE = ParseMode.COMPAT;
73+
74+
public static final ParseMode PARSE_MODE;
75+
static {
76+
PrivilegedAction<String> action = () ->
77+
System.getProperty(PARSE_MODE_PROP, DEFAULT_PARSE_MODE.toString());
78+
ParseMode parseMode = DEFAULT_PARSE_MODE;
79+
try {
80+
@SuppressWarnings("removal")
81+
String mode = AccessController.doPrivileged(action);
82+
parseMode = ParseMode.valueOf(mode.toUpperCase(Locale.ROOT));
83+
} catch (Throwable t) {
84+
parseMode = DEFAULT_PARSE_MODE;
85+
} finally {
86+
PARSE_MODE = parseMode;
87+
}
88+
}
89+
6790
private boolean useSsl = false;
6891
private String DN = null;
6992
private String attributes = null;
@@ -83,7 +106,7 @@ public LdapURL(String url) throws NamingException {
83106
useSsl = scheme.equalsIgnoreCase("ldaps");
84107

85108
if (! (scheme.equalsIgnoreCase("ldap") || useSsl)) {
86-
throw new MalformedURLException("Not an LDAP URL: " + url);
109+
throw newInvalidURISchemeException(url);
87110
}
88111

89112
parsePathAndQuery(); // DN, attributes, scope, filter, extensions
@@ -99,6 +122,21 @@ public LdapURL(String url) throws NamingException {
99122
}
100123
}
101124

125+
@Override
126+
protected MalformedURLException newInvalidURISchemeException(String uri) {
127+
return new MalformedURLException("Not an LDAP URL: " + uri);
128+
}
129+
130+
@Override
131+
protected boolean isSchemeOnly(String uri) {
132+
return isLdapSchemeOnly(uri);
133+
}
134+
135+
@Override
136+
protected ParseMode parseMode() {
137+
return PARSE_MODE;
138+
}
139+
102140
/**
103141
* Returns true if the URL is an LDAPS URL.
104142
*/
@@ -151,13 +189,33 @@ public static String[] fromList(String urlList) throws NamingException {
151189
StringTokenizer st = new StringTokenizer(urlList, " ");
152190

153191
while (st.hasMoreTokens()) {
154-
urls[i++] = st.nextToken();
192+
// we don't accept scheme-only URLs here
193+
urls[i++] = validateURI(st.nextToken());
155194
}
156195
String[] trimmed = new String[i];
157196
System.arraycopy(urls, 0, trimmed, 0, i);
158197
return trimmed;
159198
}
160199

200+
public static boolean isLdapSchemeOnly(String uri) {
201+
return "ldap:".equals(uri) || "ldaps:".equals(uri);
202+
}
203+
204+
public static String validateURI(String uri) {
205+
// no validation in legacy mode parsing
206+
if (PARSE_MODE == ParseMode.LEGACY) {
207+
return uri;
208+
}
209+
210+
// special case of scheme-only URIs
211+
if (isLdapSchemeOnly(uri)) {
212+
return uri;
213+
}
214+
215+
// use java.net.URI to validate the uri syntax
216+
return URI.create(uri).toString();
217+
}
218+
161219
/**
162220
* Determines whether an LDAP URL has query components.
163221
*/
@@ -181,7 +239,8 @@ static String toUrlString(String host, int port, String dn, boolean useSsl)
181239
String p = (port != -1) ? (":" + port) : "";
182240
String d = (dn != null) ? ("/" + UrlUtil.encode(dn, "UTF8")) : "";
183241

184-
return useSsl ? "ldaps://" + h + p + d : "ldap://" + h + p + d;
242+
String uri = useSsl ? "ldaps://" + h + p + d : "ldap://" + h + p + d;
243+
return validateURI(uri);
185244
} catch (UnsupportedEncodingException e) {
186245
// UTF8 should always be supported
187246
throw new IllegalStateException("UTF-8 encoding unavailable");

src/java.naming/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,8 @@
3232
import java.util.Hashtable;
3333
import java.net.MalformedURLException;
3434

35+
import com.sun.jndi.toolkit.url.Uri.ParseMode;
36+
3537
/**
3638
* This abstract class is a generic URL context that accepts as the
3739
* name argument either a string URL or a Name whose first component
@@ -48,6 +50,7 @@
4850
* @author Rosanna Lee
4951
*/
5052
public abstract class GenericURLContext implements Context {
53+
5154
protected Hashtable<String, Object> myEnv = null;
5255

5356
@SuppressWarnings("unchecked") // Expect Hashtable<String, Object>
@@ -161,8 +164,18 @@ protected String getURLPrefix(String url) throws NamingException {
161164
if (url.startsWith("//", start)) {
162165
start += 2; // skip double slash
163166

164-
// find last slash
165-
int posn = url.indexOf('/', start);
167+
// find where the authority component ends
168+
// and the rest of the URL starts
169+
int slash = url.indexOf('/', start);
170+
int qmark = url.indexOf('?', start);
171+
int fmark = url.indexOf('#', start);
172+
if (fmark > -1 && qmark > fmark) qmark = -1;
173+
if (fmark > -1 && slash > fmark) slash = -1;
174+
if (qmark > -1 && slash > qmark) slash = -1;
175+
int posn = slash > -1 ? slash
176+
: (qmark > -1 ? qmark
177+
: (fmark > -1 ? fmark
178+
: url.length()));
166179
if (posn >= 0) {
167180
start = posn;
168181
} else {

0 commit comments

Comments
 (0)