mirror of
https://github.com/moparisthebest/keepass2android
synced 2025-01-30 14:40:21 -05:00
Support for Digest Auth. Little "hacky" due to Bug (?) in Mono (for Android)
This commit is contained in:
parent
8238f9f76f
commit
7a065a9fdc
@ -119,13 +119,6 @@ namespace KeePassLib.Serialization
|
||||
|
||||
internal static void ConfigureWebClient(WebClient wc)
|
||||
{
|
||||
// Not implemented and ignored in Mono < 2.10
|
||||
try
|
||||
{
|
||||
wc.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
|
||||
}
|
||||
catch(NotImplementedException) { }
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
|
||||
try
|
||||
{
|
||||
@ -189,22 +182,50 @@ namespace KeePassLib.Serialization
|
||||
ValidateServerCertificate;
|
||||
}
|
||||
|
||||
private static IOWebClient CreateWebClient(IOConnectionInfo ioc)
|
||||
private static IOWebClient CreateWebClient(IOConnectionInfo ioc, bool digestAuth)
|
||||
{
|
||||
PrepareWebAccess();
|
||||
|
||||
IOWebClient wc = new IOWebClient();
|
||||
ConfigureWebClient(wc);
|
||||
|
||||
if((ioc.UserName.Length > 0) || (ioc.Password.Length > 0))
|
||||
if ((ioc.UserName.Length > 0) || (ioc.Password.Length > 0))
|
||||
{
|
||||
//set the credentials without a cache (in case the cache below fails:
|
||||
wc.Credentials = new NetworkCredential(ioc.UserName, ioc.Password);
|
||||
|
||||
if (digestAuth)
|
||||
{
|
||||
//try to use the credential cache to access with Digest support:
|
||||
try
|
||||
{
|
||||
var credentialCache = new CredentialCache();
|
||||
|
||||
credentialCache.Add(
|
||||
new Uri(new Uri(ioc.Path).GetLeftPart(UriPartial.Authority)),
|
||||
"Digest",
|
||||
new NetworkCredential(ioc.UserName, ioc.Password)
|
||||
);
|
||||
|
||||
|
||||
wc.Credentials = credentialCache;
|
||||
} catch (NotImplementedException e)
|
||||
{
|
||||
Android.Util.Log.Debug("DEBUG", e.ToString());
|
||||
} catch (Exception e)
|
||||
{
|
||||
Android.Util.Log.Debug("DEBUG", e.ToString());
|
||||
Debug.Assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(NativeLib.IsUnix()) // Mono requires credentials
|
||||
wc.Credentials = new NetworkCredential("anonymous", string.Empty);
|
||||
|
||||
return wc;
|
||||
}
|
||||
|
||||
private static WebRequest CreateWebRequest(IOConnectionInfo ioc)
|
||||
private static WebRequest CreateWebRequest(IOConnectionInfo ioc, bool digestAuth)
|
||||
{
|
||||
PrepareWebAccess();
|
||||
|
||||
@ -212,7 +233,21 @@ namespace KeePassLib.Serialization
|
||||
ConfigureWebRequest(req);
|
||||
|
||||
if((ioc.UserName.Length > 0) || (ioc.Password.Length > 0))
|
||||
{
|
||||
req.Credentials = new NetworkCredential(ioc.UserName, ioc.Password);
|
||||
|
||||
if (digestAuth)
|
||||
{
|
||||
var credentialCache = new CredentialCache();
|
||||
credentialCache.Add(
|
||||
new Uri(new Uri(ioc.Path).GetLeftPart(UriPartial.Authority)), // request url's host
|
||||
"Digest", // authentication type
|
||||
new NetworkCredential(ioc.UserName, ioc.Password) // credentials
|
||||
);
|
||||
|
||||
req.Credentials = credentialCache;
|
||||
}
|
||||
}
|
||||
else if(NativeLib.IsUnix()) // Mono requires credentials
|
||||
req.Credentials = new NetworkCredential("anonymous", string.Empty);
|
||||
|
||||
@ -221,15 +256,27 @@ namespace KeePassLib.Serialization
|
||||
|
||||
public static Stream OpenRead(IOConnectionInfo ioc)
|
||||
{
|
||||
if(StrUtil.IsDataUri(ioc.Path))
|
||||
if (StrUtil.IsDataUri(ioc.Path))
|
||||
{
|
||||
byte[] pbData = StrUtil.DataUriToData(ioc.Path);
|
||||
if(pbData != null) return new MemoryStream(pbData, false);
|
||||
if (pbData != null)
|
||||
return new MemoryStream(pbData, false);
|
||||
}
|
||||
|
||||
if(ioc.IsLocalFile()) return OpenReadLocal(ioc);
|
||||
if (ioc.IsLocalFile())
|
||||
return OpenReadLocal(ioc);
|
||||
|
||||
try
|
||||
{
|
||||
return CreateWebClient(ioc, false).OpenRead(new Uri(ioc.Path));
|
||||
} catch (WebException ex)
|
||||
{
|
||||
if ((ex.Response is HttpWebResponse) && (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.Unauthorized))
|
||||
return CreateWebClient(ioc, true).OpenRead(new Uri(ioc.Path));
|
||||
else
|
||||
throw ex;
|
||||
}
|
||||
|
||||
return CreateWebClient(ioc).OpenRead(new Uri(ioc.Path));
|
||||
}
|
||||
#else
|
||||
public static Stream OpenRead(IOConnectionInfo ioc)
|
||||
@ -248,20 +295,20 @@ namespace KeePassLib.Serialization
|
||||
|
||||
class UploadOnCloseMemoryStream: MemoryStream
|
||||
{
|
||||
System.Net.WebClient webClient;
|
||||
IOConnectionInfo ioc;
|
||||
string method;
|
||||
Uri destinationFilePath;
|
||||
|
||||
public UploadOnCloseMemoryStream(System.Net.WebClient _webClient, string _method, Uri _destinationFilePath)
|
||||
public UploadOnCloseMemoryStream(IOConnectionInfo _ioc, string _method, Uri _destinationFilePath)
|
||||
{
|
||||
this.webClient = _webClient;
|
||||
ioc = _ioc;
|
||||
this.method = _method;
|
||||
this.destinationFilePath = _destinationFilePath;
|
||||
}
|
||||
|
||||
public UploadOnCloseMemoryStream(System.Net.WebClient _webClient, Uri _destinationFilePath)
|
||||
public UploadOnCloseMemoryStream(IOConnectionInfo _ioc, Uri _destinationFilePath)
|
||||
{
|
||||
this.webClient = _webClient;
|
||||
this.ioc = _ioc;
|
||||
this.method = null;
|
||||
this.destinationFilePath = _destinationFilePath;
|
||||
}
|
||||
@ -269,6 +316,21 @@ namespace KeePassLib.Serialization
|
||||
public override void Close()
|
||||
{
|
||||
base.Close();
|
||||
try
|
||||
{
|
||||
uploadData(IOConnection.CreateWebClient(ioc, false));
|
||||
} catch (WebException ex)
|
||||
{
|
||||
if ((ex.Response is HttpWebResponse) && (((HttpWebResponse) ex.Response).StatusCode == HttpStatusCode.Unauthorized))
|
||||
uploadData(IOConnection.CreateWebClient(ioc, true));
|
||||
else
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uploadData(WebClient webClient)
|
||||
{
|
||||
if (method != null)
|
||||
{
|
||||
webClient.UploadData(destinationFilePath, method, this.ToArray());
|
||||
@ -276,7 +338,6 @@ namespace KeePassLib.Serialization
|
||||
{
|
||||
webClient.UploadData(destinationFilePath, this.ToArray());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,9 +354,9 @@ namespace KeePassLib.Serialization
|
||||
if(NativeLib.IsUnix() && (uri.Scheme.Equals(Uri.UriSchemeHttp,
|
||||
StrUtil.CaseIgnoreCmp) || uri.Scheme.Equals(Uri.UriSchemeHttps,
|
||||
StrUtil.CaseIgnoreCmp)))
|
||||
return new UploadOnCloseMemoryStream(CreateWebClient(ioc), WebRequestMethods.Http.Put, uri);
|
||||
return new UploadOnCloseMemoryStream(ioc, WebRequestMethods.Http.Put, uri);
|
||||
|
||||
return new UploadOnCloseMemoryStream(CreateWebClient(ioc), uri);
|
||||
return new UploadOnCloseMemoryStream(ioc, uri);
|
||||
}
|
||||
#else
|
||||
public static Stream OpenWrite(IOConnectionInfo ioc)
|
||||
@ -352,25 +413,45 @@ namespace KeePassLib.Serialization
|
||||
return true;
|
||||
}
|
||||
|
||||
delegate void DoWithRequest(WebRequest req);
|
||||
|
||||
|
||||
static void RepeatWithDigestOnFail(IOConnectionInfo ioc, DoWithRequest f)
|
||||
{
|
||||
WebRequest req = CreateWebRequest(ioc, false);
|
||||
try{
|
||||
f(req);
|
||||
}
|
||||
catch (WebException ex)
|
||||
{
|
||||
if ((ex.Response is HttpWebResponse) && (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.Unauthorized))
|
||||
{
|
||||
req = CreateWebRequest(ioc, true);
|
||||
f(req);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void DeleteFile(IOConnectionInfo ioc)
|
||||
{
|
||||
if(ioc.IsLocalFile()) { File.Delete(ioc.Path); return; }
|
||||
|
||||
#if !KeePassLibSD
|
||||
WebRequest req = CreateWebRequest(ioc);
|
||||
if(req != null)
|
||||
{
|
||||
if(req is HttpWebRequest) req.Method = "DELETE";
|
||||
else if(req is FtpWebRequest) req.Method = WebRequestMethods.Ftp.DeleteFile;
|
||||
else if(req is FileWebRequest)
|
||||
RepeatWithDigestOnFail(ioc, (WebRequest req) => {
|
||||
if(req != null)
|
||||
{
|
||||
File.Delete(UrlUtil.FileUrlToPath(ioc.Path));
|
||||
return;
|
||||
}
|
||||
else req.Method = WrmDeleteFile;
|
||||
if(req is HttpWebRequest) req.Method = "DELETE";
|
||||
else if(req is FtpWebRequest) req.Method = WebRequestMethods.Ftp.DeleteFile;
|
||||
else if(req is FileWebRequest)
|
||||
{
|
||||
File.Delete(UrlUtil.FileUrlToPath(ioc.Path));
|
||||
return;
|
||||
}
|
||||
else req.Method = WrmDeleteFile;
|
||||
|
||||
DisposeResponse(req.GetResponse(), true);
|
||||
}
|
||||
DisposeResponse(req.GetResponse(), true);
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -388,8 +469,7 @@ namespace KeePassLib.Serialization
|
||||
if(iocFrom.IsLocalFile()) { File.Move(iocFrom.Path, iocTo.Path); return; }
|
||||
|
||||
#if !KeePassLibSD
|
||||
WebRequest req = CreateWebRequest(iocFrom);
|
||||
if(req != null)
|
||||
RepeatWithDigestOnFail(iocFrom, (WebRequest req)=> { if(req != null)
|
||||
{
|
||||
if(req is HttpWebRequest)
|
||||
{
|
||||
@ -415,6 +495,8 @@ namespace KeePassLib.Serialization
|
||||
|
||||
DisposeResponse(req.GetResponse(), true);
|
||||
}
|
||||
});
|
||||
|
||||
#endif
|
||||
|
||||
// using(Stream sIn = IOConnection.OpenRead(iocFrom))
|
||||
@ -435,9 +517,11 @@ namespace KeePassLib.Serialization
|
||||
{
|
||||
try
|
||||
{
|
||||
WebRequest req = CreateWebRequest(ioc);
|
||||
req.Method = strMethod;
|
||||
DisposeResponse(req.GetResponse(), true);
|
||||
RepeatWithDigestOnFail(ioc, (WebRequest req)=> {
|
||||
req.Method = strMethod;
|
||||
DisposeResponse(req.GetResponse(), true);
|
||||
|
||||
});
|
||||
}
|
||||
catch(Exception) { return false; }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user