PageRenderTime 2972ms CodeModel.GetById 44ms RepoModel.GetById 1ms app.codeStats 0ms

/core/java/android/net/http/HttpAuthHeader.java

https://gitlab.com/AvayKumar/android_frameworks_base
Java | 424 lines | 201 code | 52 blank | 171 comment | 58 complexity | 9ca471563468e2861073376c795e805e MD5 | raw file
  1. /*
  2. * Copyright (C) 2007 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package android.net.http;
  17. import java.util.Locale;
  18. /**
  19. * HttpAuthHeader: a class to store HTTP authentication-header parameters.
  20. * For more information, see: RFC 2617: HTTP Authentication.
  21. *
  22. * {@hide}
  23. */
  24. public class HttpAuthHeader {
  25. /**
  26. * Possible HTTP-authentication header tokens to search for:
  27. */
  28. public final static String BASIC_TOKEN = "Basic";
  29. public final static String DIGEST_TOKEN = "Digest";
  30. private final static String REALM_TOKEN = "realm";
  31. private final static String NONCE_TOKEN = "nonce";
  32. private final static String STALE_TOKEN = "stale";
  33. private final static String OPAQUE_TOKEN = "opaque";
  34. private final static String QOP_TOKEN = "qop";
  35. private final static String ALGORITHM_TOKEN = "algorithm";
  36. /**
  37. * An authentication scheme. We currently support two different schemes:
  38. * HttpAuthHeader.BASIC - basic, and
  39. * HttpAuthHeader.DIGEST - digest (algorithm=MD5, QOP="auth").
  40. */
  41. private int mScheme;
  42. public static final int UNKNOWN = 0;
  43. public static final int BASIC = 1;
  44. public static final int DIGEST = 2;
  45. /**
  46. * A flag, indicating that the previous request from the client was
  47. * rejected because the nonce value was stale. If stale is TRUE
  48. * (case-insensitive), the client may wish to simply retry the request
  49. * with a new encrypted response, without reprompting the user for a
  50. * new username and password.
  51. */
  52. private boolean mStale;
  53. /**
  54. * A string to be displayed to users so they know which username and
  55. * password to use.
  56. */
  57. private String mRealm;
  58. /**
  59. * A server-specified data string which should be uniquely generated
  60. * each time a 401 response is made.
  61. */
  62. private String mNonce;
  63. /**
  64. * A string of data, specified by the server, which should be returned
  65. * by the client unchanged in the Authorization header of subsequent
  66. * requests with URIs in the same protection space.
  67. */
  68. private String mOpaque;
  69. /**
  70. * This directive is optional, but is made so only for backward
  71. * compatibility with RFC 2069 [6]; it SHOULD be used by all
  72. * implementations compliant with this version of the Digest scheme.
  73. * If present, it is a quoted string of one or more tokens indicating
  74. * the "quality of protection" values supported by the server. The
  75. * value "auth" indicates authentication; the value "auth-int"
  76. * indicates authentication with integrity protection.
  77. */
  78. private String mQop;
  79. /**
  80. * A string indicating a pair of algorithms used to produce the digest
  81. * and a checksum. If this is not present it is assumed to be "MD5".
  82. */
  83. private String mAlgorithm;
  84. /**
  85. * Is this authentication request a proxy authentication request?
  86. */
  87. private boolean mIsProxy;
  88. /**
  89. * Username string we get from the user.
  90. */
  91. private String mUsername;
  92. /**
  93. * Password string we get from the user.
  94. */
  95. private String mPassword;
  96. /**
  97. * Creates a new HTTP-authentication header object from the
  98. * input header string.
  99. * The header string is assumed to contain parameters of at
  100. * most one authentication-scheme (ensured by the caller).
  101. */
  102. public HttpAuthHeader(String header) {
  103. if (header != null) {
  104. parseHeader(header);
  105. }
  106. }
  107. /**
  108. * @return True iff this is a proxy authentication header.
  109. */
  110. public boolean isProxy() {
  111. return mIsProxy;
  112. }
  113. /**
  114. * Marks this header as a proxy authentication header.
  115. */
  116. public void setProxy() {
  117. mIsProxy = true;
  118. }
  119. /**
  120. * @return The username string.
  121. */
  122. public String getUsername() {
  123. return mUsername;
  124. }
  125. /**
  126. * Sets the username string.
  127. */
  128. public void setUsername(String username) {
  129. mUsername = username;
  130. }
  131. /**
  132. * @return The password string.
  133. */
  134. public String getPassword() {
  135. return mPassword;
  136. }
  137. /**
  138. * Sets the password string.
  139. */
  140. public void setPassword(String password) {
  141. mPassword = password;
  142. }
  143. /**
  144. * @return True iff this is the BASIC-authentication request.
  145. */
  146. public boolean isBasic () {
  147. return mScheme == BASIC;
  148. }
  149. /**
  150. * @return True iff this is the DIGEST-authentication request.
  151. */
  152. public boolean isDigest() {
  153. return mScheme == DIGEST;
  154. }
  155. /**
  156. * @return The authentication scheme requested. We currently
  157. * support two schemes:
  158. * HttpAuthHeader.BASIC - basic, and
  159. * HttpAuthHeader.DIGEST - digest (algorithm=MD5, QOP="auth").
  160. */
  161. public int getScheme() {
  162. return mScheme;
  163. }
  164. /**
  165. * @return True if indicating that the previous request from
  166. * the client was rejected because the nonce value was stale.
  167. */
  168. public boolean getStale() {
  169. return mStale;
  170. }
  171. /**
  172. * @return The realm value or null if there is none.
  173. */
  174. public String getRealm() {
  175. return mRealm;
  176. }
  177. /**
  178. * @return The nonce value or null if there is none.
  179. */
  180. public String getNonce() {
  181. return mNonce;
  182. }
  183. /**
  184. * @return The opaque value or null if there is none.
  185. */
  186. public String getOpaque() {
  187. return mOpaque;
  188. }
  189. /**
  190. * @return The QOP ("quality-of_protection") value or null if
  191. * there is none. The QOP value is always lower-case.
  192. */
  193. public String getQop() {
  194. return mQop;
  195. }
  196. /**
  197. * @return The name of the algorithm used or null if there is
  198. * none. By default, MD5 is used.
  199. */
  200. public String getAlgorithm() {
  201. return mAlgorithm;
  202. }
  203. /**
  204. * @return True iff the authentication scheme requested by the
  205. * server is supported; currently supported schemes:
  206. * BASIC,
  207. * DIGEST (only algorithm="md5", no qop or qop="auth).
  208. */
  209. public boolean isSupportedScheme() {
  210. // it is a good idea to enforce non-null realms!
  211. if (mRealm != null) {
  212. if (mScheme == BASIC) {
  213. return true;
  214. } else {
  215. if (mScheme == DIGEST) {
  216. return
  217. mAlgorithm.equals("md5") &&
  218. (mQop == null || mQop.equals("auth"));
  219. }
  220. }
  221. }
  222. return false;
  223. }
  224. /**
  225. * Parses the header scheme name and then scheme parameters if
  226. * the scheme is supported.
  227. */
  228. private void parseHeader(String header) {
  229. if (HttpLog.LOGV) {
  230. HttpLog.v("HttpAuthHeader.parseHeader(): header: " + header);
  231. }
  232. if (header != null) {
  233. String parameters = parseScheme(header);
  234. if (parameters != null) {
  235. // if we have a supported scheme
  236. if (mScheme != UNKNOWN) {
  237. parseParameters(parameters);
  238. }
  239. }
  240. }
  241. }
  242. /**
  243. * Parses the authentication scheme name. If we have a Digest
  244. * scheme, sets the algorithm value to the default of MD5.
  245. * @return The authentication scheme parameters string to be
  246. * parsed later (if the scheme is supported) or null if failed
  247. * to parse the scheme (the header value is null?).
  248. */
  249. private String parseScheme(String header) {
  250. if (header != null) {
  251. int i = header.indexOf(' ');
  252. if (i >= 0) {
  253. String scheme = header.substring(0, i).trim();
  254. if (scheme.equalsIgnoreCase(DIGEST_TOKEN)) {
  255. mScheme = DIGEST;
  256. // md5 is the default algorithm!!!
  257. mAlgorithm = "md5";
  258. } else {
  259. if (scheme.equalsIgnoreCase(BASIC_TOKEN)) {
  260. mScheme = BASIC;
  261. }
  262. }
  263. return header.substring(i + 1);
  264. }
  265. }
  266. return null;
  267. }
  268. /**
  269. * Parses a comma-separated list of authentification scheme
  270. * parameters.
  271. */
  272. private void parseParameters(String parameters) {
  273. if (HttpLog.LOGV) {
  274. HttpLog.v("HttpAuthHeader.parseParameters():" +
  275. " parameters: " + parameters);
  276. }
  277. if (parameters != null) {
  278. int i;
  279. do {
  280. i = parameters.indexOf(',');
  281. if (i < 0) {
  282. // have only one parameter
  283. parseParameter(parameters);
  284. } else {
  285. parseParameter(parameters.substring(0, i));
  286. parameters = parameters.substring(i + 1);
  287. }
  288. } while (i >= 0);
  289. }
  290. }
  291. /**
  292. * Parses a single authentication scheme parameter. The parameter
  293. * string is expected to follow the format: PARAMETER=VALUE.
  294. */
  295. private void parseParameter(String parameter) {
  296. if (parameter != null) {
  297. // here, we are looking for the 1st occurence of '=' only!!!
  298. int i = parameter.indexOf('=');
  299. if (i >= 0) {
  300. String token = parameter.substring(0, i).trim();
  301. String value =
  302. trimDoubleQuotesIfAny(parameter.substring(i + 1).trim());
  303. if (HttpLog.LOGV) {
  304. HttpLog.v("HttpAuthHeader.parseParameter():" +
  305. " token: " + token +
  306. " value: " + value);
  307. }
  308. if (token.equalsIgnoreCase(REALM_TOKEN)) {
  309. mRealm = value;
  310. } else {
  311. if (mScheme == DIGEST) {
  312. parseParameter(token, value);
  313. }
  314. }
  315. }
  316. }
  317. }
  318. /**
  319. * If the token is a known parameter name, parses and initializes
  320. * the token value.
  321. */
  322. private void parseParameter(String token, String value) {
  323. if (token != null && value != null) {
  324. if (token.equalsIgnoreCase(NONCE_TOKEN)) {
  325. mNonce = value;
  326. return;
  327. }
  328. if (token.equalsIgnoreCase(STALE_TOKEN)) {
  329. parseStale(value);
  330. return;
  331. }
  332. if (token.equalsIgnoreCase(OPAQUE_TOKEN)) {
  333. mOpaque = value;
  334. return;
  335. }
  336. if (token.equalsIgnoreCase(QOP_TOKEN)) {
  337. mQop = value.toLowerCase(Locale.ROOT);
  338. return;
  339. }
  340. if (token.equalsIgnoreCase(ALGORITHM_TOKEN)) {
  341. mAlgorithm = value.toLowerCase(Locale.ROOT);
  342. return;
  343. }
  344. }
  345. }
  346. /**
  347. * Parses and initializes the 'stale' paramer value. Any value
  348. * different from case-insensitive "true" is considered "false".
  349. */
  350. private void parseStale(String value) {
  351. if (value != null) {
  352. if (value.equalsIgnoreCase("true")) {
  353. mStale = true;
  354. }
  355. }
  356. }
  357. /**
  358. * Trims double-quotes around a parameter value if there are any.
  359. * @return The string value without the outermost pair of double-
  360. * quotes or null if the original value is null.
  361. */
  362. static private String trimDoubleQuotesIfAny(String value) {
  363. if (value != null) {
  364. int len = value.length();
  365. if (len > 2 &&
  366. value.charAt(0) == '\"' && value.charAt(len - 1) == '\"') {
  367. return value.substring(1, len - 1);
  368. }
  369. }
  370. return value;
  371. }
  372. }