// this method is only called as part of an assert internal bool IsEqualTo(object compObject) { if ((object)compObject == null) { return(false); } if ((object)this == (object)compObject) { return(true); } NetworkCredential compCred = compObject as NetworkCredential; if ((object)compCred == null) { return(false); } #if FEATURE_PAL return(InternalGetUserName() == compCred.InternalGetUserName() && InternalGetPassword() == compCred.InternalGetPassword() && InternalGetDomain() == compCred.InternalGetDomain()); #else //!FEATURE_PAL return(InternalGetUserName() == compCred.InternalGetUserName() && InternalGetDomain() == compCred.InternalGetDomain() && UnsafeNclNativeMethods.SecureStringHelper.AreEqualValues(InternalGetSecurePassword(), compCred.InternalGetSecurePassword())); #endif //!FEATURE_PAL }
internal bool IsEqualTo(object compObject) { if ((object)compObject == null) { return(false); } if ((object)this == (object)compObject) { return(true); } NetworkCredential compCred = compObject as NetworkCredential; if ((object)compCred == null) { return(false); } return(InternalGetUserName() == compCred.InternalGetUserName() && InternalGetPassword() == compCred.InternalGetPassword() && InternalGetDomain() == compCred.InternalGetDomain()); }
private void Initialize(bool isServer, string package, NetworkCredential credential, string spn, ContextFlags requestedContextFlags, System.Security.Authentication.ExtendedProtection.ChannelBinding channelBinding) { this.m_TokenSize = SSPIWrapper.GetVerifyPackageInfo(GlobalSSPI.SSPIAuth, package, true).MaxToken; this.m_IsServer = isServer; this.m_Spn = spn; this.m_SecurityContext = null; this.m_RequestedContextFlags = requestedContextFlags; this.m_Package = package; this.m_ChannelBinding = channelBinding; if (credential is SystemNetworkCredential) { this.m_CredentialsHandle = SSPIWrapper.AcquireDefaultCredential(GlobalSSPI.SSPIAuth, package, this.m_IsServer ? CredentialUse.Inbound : CredentialUse.Outbound); this.m_UniqueUserId = "/S"; } else { string userName = credential.InternalGetUserName(); string domain = credential.InternalGetDomain(); AuthIdentity authdata = new AuthIdentity(userName, credential.InternalGetPassword(), ((package == "WDigest") && ((domain == null) || (domain.Length == 0))) ? null : domain); this.m_UniqueUserId = domain + "/" + userName + "/U"; this.m_CredentialsHandle = SSPIWrapper.AcquireCredentialsHandle(GlobalSSPI.SSPIAuth, package, this.m_IsServer ? CredentialUse.Inbound : CredentialUse.Outbound, ref authdata); } }
// private void Initialize(bool isServer, string package, NetworkCredential credential, string spn, ContextFlags requestedContextFlags, ChannelBinding channelBinding) { GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::.ctor() package:" + ValidationHelper.ToString(package) + " spn:" + ValidationHelper.ToString(spn) + " flags :" + requestedContextFlags.ToString()); m_TokenSize = SSPIWrapper.GetVerifyPackageInfo(GlobalSSPI.SSPIAuth, package, true).MaxToken; m_IsServer = isServer; m_Spn = spn; m_SecurityContext = null; m_RequestedContextFlags = requestedContextFlags; m_Package = package; m_ChannelBinding = channelBinding; GlobalLog.Print("Peer SPN-> '" + m_Spn + "'"); // // check if we're using DefaultCredentials // if (credential is SystemNetworkCredential) { GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::.ctor(): using DefaultCredentials"); m_CredentialsHandle = SSPIWrapper.AcquireDefaultCredential( GlobalSSPI.SSPIAuth, package, (m_IsServer? CredentialUse.Inbound: CredentialUse.Outbound)); m_UniqueUserId = "/S"; // save off for unique connection marking ONLY used by HTTP client } else if (ComNetOS.IsWin7orLater) { unsafe { SafeSspiAuthDataHandle authData = null; try { SecurityStatus result = UnsafeNclNativeMethods.SspiHelper.SspiEncodeStringsAsAuthIdentity( credential.InternalGetUserName(), credential.InternalGetDomain(), credential.InternalGetPassword(), out authData); if (result != SecurityStatus.OK) { if (Logging.On) Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_failed_with_error, "SspiEncodeStringsAsAuthIdentity()", String.Format(CultureInfo.CurrentCulture, "0x{0:X}", (int)result))); throw new Win32Exception((int)result); } m_CredentialsHandle = SSPIWrapper.AcquireCredentialsHandle(GlobalSSPI.SSPIAuth, package, (m_IsServer ? CredentialUse.Inbound : CredentialUse.Outbound), ref authData); } finally { if (authData != null) { authData.Close(); } } } } else { // // we're not using DefaultCredentials, we need a // AuthIdentity struct to contain credentials // SECREVIEW: // we'll save username/domain in temp strings, to avoid decrypting multiple times. // password is only used once // string username = credential.InternalGetUserName(); string domain = credential.InternalGetDomain(); // ATTN: // NetworkCredential class does not differentiate between null and "" but SSPI packages treat these cases differently // For NTLM we want to keep "" for Wdigest.Dll we should use null. AuthIdentity authIdentity = new AuthIdentity(username, credential.InternalGetPassword(), (object)package == (object)NegotiationInfoClass.WDigest && (domain == null || domain.Length == 0)? null: domain); m_UniqueUserId = domain + "/" + username + "/U"; // save off for unique connection marking ONLY used by HTTP client GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::.ctor(): using authIdentity:" + authIdentity.ToString()); m_CredentialsHandle = SSPIWrapper.AcquireCredentialsHandle( GlobalSSPI.SSPIAuth, package, (m_IsServer? CredentialUse.Inbound: CredentialUse.Outbound), ref authIdentity ); } }
// // CONSIDER V.NEXT // creating a static hashtable for server nonces and keep track of nonce count // internal static Authorization Authenticate(HttpDigestChallenge digestChallenge, NetworkCredential NC, string spn, ChannelBinding binding) { string username = NC.InternalGetUserName(); if (ValidationHelper.IsBlankString(username)) { return null; } string password = NC.InternalGetPassword(); bool upgraded = IsUpgraded(digestChallenge.Nonce, binding); if (upgraded) { digestChallenge.ServiceName = spn; digestChallenge.ChannelBinding = hashChannelBinding(binding, digestChallenge.MD5provider); } if (digestChallenge.QopPresent) { if (digestChallenge.ClientNonce==null || digestChallenge.Stale) { GlobalLog.Print("HttpDigest::Authenticate() QopPresent:True, need new nonce. digestChallenge.ClientNonce:" + ValidationHelper.ToString(digestChallenge.ClientNonce) + " digestChallenge.Stale:" + digestChallenge.Stale.ToString()); if (upgraded) { digestChallenge.ClientNonce = createUpgradedNonce(digestChallenge); } else { digestChallenge.ClientNonce = createNonce(32); } digestChallenge.NonceCount = 1; } else { GlobalLog.Print("HttpDigest::Authenticate() QopPresent:True, reusing nonce. digestChallenge.NonceCount:" + digestChallenge.NonceCount.ToString()); digestChallenge.NonceCount++; } } StringBuilder authorization = new StringBuilder(); // // look at username & password, if it's not ASCII we need to attempt some // kind of encoding because we need to calculate the hash on byte[] // Charset usernameCharset = DetectCharset(username); if (!digestChallenge.UTF8Charset && usernameCharset==Charset.UTF8) { GlobalLog.Print("HttpDigest::Authenticate() can't authenticate with UNICODE username. failing auth."); return null; } Charset passwordCharset = DetectCharset(password); if (!digestChallenge.UTF8Charset && passwordCharset==Charset.UTF8) { GlobalLog.Print("HttpDigest::Authenticate() can't authenticate with UNICODE password. failing auth."); return null; } if (digestChallenge.UTF8Charset) { // on the wire always use UTF8 when the server supports it authorization.Append(pair(DA_charset, "utf-8", false)); authorization.Append(","); if (usernameCharset==Charset.UTF8) { username = CharsetEncode(username, Charset.UTF8); authorization.Append(pair(DA_username, username, true)); authorization.Append(","); } else { authorization.Append(pair(DA_username, CharsetEncode(username, Charset.UTF8), true)); authorization.Append(","); username = CharsetEncode(username, usernameCharset); } } else { // otherwise UTF8 is not required username = CharsetEncode(username, usernameCharset); authorization.Append(pair(DA_username, username, true)); authorization.Append(","); } password = CharsetEncode(password, passwordCharset); // no special encoding for the realm since we're just going to echo it back (encoding must have happened on the server). authorization.Append(pair(DA_realm, digestChallenge.Realm, true)); authorization.Append(","); authorization.Append(pair(DA_nonce, digestChallenge.Nonce, true)); authorization.Append(","); authorization.Append(pair(DA_uri, digestChallenge.Uri, true)); if (digestChallenge.QopPresent) { if (digestChallenge.Algorithm!=null) { // consider: should we default to "MD5" here? IE does authorization.Append(","); authorization.Append(pair(DA_algorithm, digestChallenge.Algorithm, true)); // IE sends quotes - IIS needs them } authorization.Append(","); authorization.Append(pair(DA_cnonce, digestChallenge.ClientNonce, true)); authorization.Append(","); authorization.Append(pair(DA_nc, digestChallenge.NonceCount.ToString("x8", NumberFormatInfo.InvariantInfo), false)); // RAID#47397 // send only the QualityOfProtection we're using // since we support only "auth" that's what we will send out authorization.Append(","); authorization.Append(pair(DA_qop, SupportedQuality, true)); // IE sends quotes - IIS needs them if (upgraded) { authorization.Append(","); authorization.Append(pair(DA_hasheddirs, HashedDirs, true)); authorization.Append(","); authorization.Append(pair(DA_servicename, digestChallenge.ServiceName, true)); authorization.Append(","); authorization.Append(pair(DA_channelbinding, digestChallenge.ChannelBinding, true)); } } // warning: this must be computed here string responseValue = HttpDigest.responseValue(digestChallenge, username, password); if (responseValue==null) { return null; } authorization.Append(","); authorization.Append(pair(DA_response, responseValue, true)); // IE sends quotes - IIS needs them if (digestChallenge.Opaque!=null) { authorization.Append(","); authorization.Append(pair(DA_opaque, digestChallenge.Opaque, true)); } GlobalLog.Print("HttpDigest::Authenticate() digestChallenge.Stale:" + digestChallenge.Stale.ToString()); // completion is decided in Update() Authorization finalAuthorization = new Authorization(DigestClient.AuthType + " " + authorization.ToString(), false); return finalAuthorization; }
private Authorization Lookup(HttpWebRequest httpWebRequest, ICredentials credentials) { NetworkCredential credential = credentials.GetCredential(httpWebRequest.ChallengedUri, Signature); if (credential == null) { return(null); } ICredentialPolicy credentialPolicy = AuthenticationManager.CredentialPolicy; if ((credentialPolicy != null) && !credentialPolicy.ShouldSendCredential(httpWebRequest.ChallengedUri, httpWebRequest, credential, this)) { return(null); } string userName = credential.InternalGetUserName(); string domain = credential.InternalGetDomain(); if (ValidationHelper.IsBlankString(userName)) { return(null); } byte[] inArray = EncodingRightGetBytes((!ValidationHelper.IsBlankString(domain) ? (domain + @"\") : "") + userName + ":" + credential.InternalGetPassword()); return(new Authorization("Basic " + Convert.ToBase64String(inArray), true)); }
/// <summary> /// <para>Creates an array of commands, that will be sent to the server</para> /// </summary> protected override PipelineEntry [] BuildCommandsList(WebRequest req) { bool resetLoggedInState = false; FtpWebRequest request = (FtpWebRequest) req; GlobalLog.Print("FtpControlStream#" + ValidationHelper.HashString(this) + "BuildCommandsList"); m_ResponseUri = request.RequestUri; ArrayList commandList = new ArrayList(); #if DEBUG // the Credentials.IsEqualTo method is only compiled in DEBUG so the assert must be restricted to DEBUG // as well // While some FTP servers support it, in general, the RFC's don't allow re-issuing the USER command to // change the authentication context of an existing logged in connection. We prevent re-using existing // connections if the credentials are different from the previous FtpWebRequest. Let's make sure that // our connection pooling code is working correctly. Debug.Assert(Credentials == null || Credentials.IsEqualTo(request.Credentials.GetCredential(request.RequestUri, "basic")), "Should not be re-using an existing connection with different credentials"); #endif if (request.EnableSsl && !UsingSecureStream) { commandList.Add(new PipelineEntry(FormatFtpCommand("AUTH", "TLS"))); // According to RFC we need to re-authorize with USER/PASS after we re-authenticate. resetLoggedInState = true; } if (resetLoggedInState) { m_LoginDirectory = null; m_EstablishedServerDirectory = null; m_RequestedServerDirectory = null; m_CurrentTypeSetting = string.Empty; if (m_LoginState == FtpLoginState.LoggedIn) m_LoginState = FtpLoginState.LoggedInButNeedsRelogin; } if (m_LoginState != FtpLoginState.LoggedIn) { Credentials = request.Credentials.GetCredential(request.RequestUri, "basic"); m_WelcomeMessage = new StringBuilder(); m_ExitMessage = new StringBuilder(); string domainUserName = string.Empty; string password = string.Empty; if (Credentials != null) { domainUserName = Credentials.InternalGetDomainUserName(); password = Credentials.InternalGetPassword(); } if (domainUserName.Length == 0 && password.Length == 0) { domainUserName = "******"; password = "******"; } commandList.Add(new PipelineEntry(FormatFtpCommand("USER", domainUserName))); commandList.Add(new PipelineEntry(FormatFtpCommand("PASS", password), PipelineEntryFlags.DontLogParameter)); // If SSL, always configure data channel encryption after authentication to maximum RFC compatibility. The RFC allows for // PBSZ/PROT commands to come either before or after the USER/PASS, but some servers require USER/PASS immediately after // the AUTH TLS command. if (request.EnableSsl && !UsingSecureStream) { commandList.Add(new PipelineEntry(FormatFtpCommand("PBSZ", "0"))); commandList.Add(new PipelineEntry(FormatFtpCommand("PROT", "P"))); } commandList.Add(new PipelineEntry(FormatFtpCommand("OPTS", "utf8 on"))); commandList.Add(new PipelineEntry(FormatFtpCommand("PWD", null))); } GetPathOption getPathOption = GetPathOption.Normal; if (request.MethodInfo.HasFlag(FtpMethodFlags.DoesNotTakeParameter)) { getPathOption = GetPathOption.AssumeNoFilename; } else if (request.MethodInfo.HasFlag(FtpMethodFlags.ParameterIsDirectory)) { getPathOption = GetPathOption.AssumeFilename; } string requestPath; string requestDirectory; string requestFilename; GetPathInfo(getPathOption, request.RequestUri, out requestPath, out requestDirectory, out requestFilename); if (requestFilename.Length == 0 && request.MethodInfo.HasFlag(FtpMethodFlags.TakesParameter)) throw new WebException(SR.GetString(SR.net_ftp_invalid_uri)); // We optimize for having the current working directory staying at the login directory. This ensure that // our relative paths work right and reduces unnecessary CWD commands. // Usually, we don't change the working directory except for some FTP commands. If necessary, // we need to reset our working directory back to the login directory. if (m_EstablishedServerDirectory != null && m_LoginDirectory != null && m_EstablishedServerDirectory != m_LoginDirectory) { commandList.Add(new PipelineEntry(FormatFtpCommand("CWD", m_LoginDirectory), PipelineEntryFlags.UserCommand)); m_RequestedServerDirectory = m_LoginDirectory; } // For most commands, we don't need to navigate to the directory since we pass in the full // path as part of the FTP protocol command. However, some commands require it. if (request.MethodInfo.HasFlag(FtpMethodFlags.MustChangeWorkingDirectoryToPath) && requestDirectory.Length > 0) { commandList.Add(new PipelineEntry(FormatFtpCommand("CWD", requestDirectory), PipelineEntryFlags.UserCommand)); m_RequestedServerDirectory = requestDirectory; } if (request.CacheProtocol != null && request.CacheProtocol.ProtocolStatus == CacheValidationStatus.DoNotTakeFromCache && request.MethodInfo.Operation == FtpOperation.DownloadFile) commandList.Add(new PipelineEntry(FormatFtpCommand("MDTM", requestPath))); if (!request.MethodInfo.IsCommandOnly) { // This is why having a protocol logic on the connection is a bad idea if (request.CacheProtocol == null || request.CacheProtocol.ProtocolStatus != CacheValidationStatus.Continue) { string requestedTypeSetting = request.UseBinary ? "I" : "A"; if (m_CurrentTypeSetting != requestedTypeSetting) { commandList.Add(new PipelineEntry(FormatFtpCommand("TYPE", requestedTypeSetting))); m_CurrentTypeSetting = requestedTypeSetting; } if (request.UsePassive) { string passiveCommand = (ServerAddress.AddressFamily == AddressFamily.InterNetwork) ? "PASV" : "EPSV"; commandList.Add(new PipelineEntry(FormatFtpCommand(passiveCommand, null), PipelineEntryFlags.CreateDataConnection)); } else { string portCommand = (ServerAddress.AddressFamily == AddressFamily.InterNetwork) ? "PORT" : "EPRT"; CreateFtpListenerSocket(request); commandList.Add(new PipelineEntry(FormatFtpCommand(portCommand, GetPortCommandLine(request)))); } if (request.CacheProtocol != null && request.CacheProtocol.ProtocolStatus == CacheValidationStatus.CombineCachedAndServerResponse) { // Combining partial cache with the reminder using "REST" if (request.CacheProtocol.Validator.CacheEntry.StreamSize > 0) commandList.Add(new PipelineEntry(FormatFtpCommand("REST", request.CacheProtocol.Validator.CacheEntry.StreamSize.ToString(CultureInfo.InvariantCulture)))); } else if (request.ContentOffset > 0) { // REST command must always be the last sent before the main file command is sent. commandList.Add(new PipelineEntry(FormatFtpCommand("REST", request.ContentOffset.ToString(CultureInfo.InvariantCulture)))); } } else { // revalidating GetFileSize = "SIZE" GetDateTimeStamp = "MDTM" commandList.Add(new PipelineEntry(FormatFtpCommand("SIZE", requestPath))); commandList.Add(new PipelineEntry(FormatFtpCommand("MDTM", requestPath))); } } // // Suppress the data file if this is a revalidation request // if (request.CacheProtocol == null || request.CacheProtocol.ProtocolStatus != CacheValidationStatus.Continue) { PipelineEntryFlags flags = PipelineEntryFlags.UserCommand; if (!request.MethodInfo.IsCommandOnly) { flags |= PipelineEntryFlags.GiveDataStream; if (!request.UsePassive) flags |= PipelineEntryFlags.CreateDataConnection; } if (request.MethodInfo.Operation == FtpOperation.Rename) { string baseDir = (requestDirectory == string.Empty) ? string.Empty : requestDirectory + "/"; commandList.Add(new PipelineEntry(FormatFtpCommand("RNFR", baseDir + requestFilename), flags)); string renameTo; if (!string.IsNullOrEmpty(request.RenameTo) && request.RenameTo.StartsWith("/", StringComparison.OrdinalIgnoreCase)) { renameTo = request.RenameTo; // Absolute path } else { renameTo = baseDir + request.RenameTo; // Relative path } commandList.Add(new PipelineEntry(FormatFtpCommand("RNTO", renameTo), flags)); } else if (request.MethodInfo.HasFlag(FtpMethodFlags.DoesNotTakeParameter)) { commandList.Add(new PipelineEntry(FormatFtpCommand(request.Method, string.Empty), flags)); } else if (request.MethodInfo.HasFlag(FtpMethodFlags.MustChangeWorkingDirectoryToPath)) { commandList.Add(new PipelineEntry(FormatFtpCommand(request.Method, requestFilename), flags)); } else { commandList.Add(new PipelineEntry(FormatFtpCommand(request.Method, requestPath), flags)); } if (!request.KeepAlive) { commandList.Add(new PipelineEntry(FormatFtpCommand("QUIT", null))); } } return (PipelineEntry []) commandList.ToArray(typeof(PipelineEntry)); }
/// <summary> /// <para>Creates an array of commands, that will be sent to the server</para> /// </summary> protected override PipelineEntry [] BuildCommandsList(WebRequest req) { FtpWebRequest request = (FtpWebRequest) req; GlobalLog.Print("FtpControlStream#" + ValidationHelper.HashString(this) + "BuildCommandsList"); m_ResponseUri = request.RequestUri; ArrayList commandList = new ArrayList(); if ((m_LastRequestWasUnknownMethod && !request.MethodInfo.IsUnknownMethod) || Credentials == null || !Credentials.IsEqualTo(request.Credentials.GetCredential(request.RequestUri, "basic"))) { m_PreviousServerPath = null; m_NewServerPath = null; m_LoginDirectory = null; if (m_LoginState == FtpLoginState.LoggedIn) m_LoginState = FtpLoginState.LoggedInButNeedsRelogin; } m_LastRequestWasUnknownMethod = request.MethodInfo.IsUnknownMethod; if (request.EnableSsl && !UsingSecureStream) { commandList.Add(new PipelineEntry(FormatFtpCommand("AUTH", "TLS"))); commandList.Add(new PipelineEntry(FormatFtpCommand("PBSZ", "0"))); commandList.Add(new PipelineEntry(FormatFtpCommand("PROT", "P"))); // According to RFC we need to re-authorize with USER/PASS after we re-authenticate. if (m_LoginState == FtpLoginState.LoggedIn) m_LoginState = FtpLoginState.LoggedInButNeedsRelogin; } if (m_LoginState != FtpLoginState.LoggedIn) { Credentials = request.Credentials.GetCredential(request.RequestUri, "basic"); m_WelcomeMessage = new StringBuilder(); m_ExitMessage = new StringBuilder(); string domainUserName = string.Empty; string password = string.Empty; if (Credentials != null) { domainUserName = Credentials.InternalGetDomainUserName(); password = Credentials.InternalGetPassword(); } if (domainUserName.Length == 0 && password.Length == 0) { domainUserName = "******"; password = "******"; } commandList.Add(new PipelineEntry(FormatFtpCommand("USER", domainUserName))); commandList.Add(new PipelineEntry(FormatFtpCommand("PASS", password), PipelineEntryFlags.DontLogParameter)); commandList.Add(new PipelineEntry(FormatFtpCommand("OPTS", "utf8 on"))); commandList.Add(new PipelineEntry(FormatFtpCommand("PWD", null))); } GetPathOption getPathOption = GetPathOption.Normal; if (request.MethodInfo.HasFlag(FtpMethodFlags.DoesNotTakeParameter)) { getPathOption = GetPathOption.AssumeNoFilename; } else if (request.MethodInfo.HasFlag(FtpMethodFlags.ParameterIsDirectory)) { getPathOption = GetPathOption.AssumeFilename; } string requestPath = null; string requestFilename = null; GetPathAndFilename(getPathOption, request.RequestUri, ref requestPath, ref requestFilename, ref m_IsRootPath); if (requestFilename.Length == 0 && request.MethodInfo.HasFlag(FtpMethodFlags.TakesParameter)) throw new WebException(SR.GetString(SR.net_ftp_invalid_uri)); string newServerPath = requestPath; if (m_PreviousServerPath != newServerPath) { if (!m_IsRootPath && m_LoginState == FtpLoginState.LoggedIn && m_LoginDirectory != null) { newServerPath = m_LoginDirectory+newServerPath; } m_NewServerPath = newServerPath; commandList.Add(new PipelineEntry(FormatFtpCommand("CWD", newServerPath), PipelineEntryFlags.UserCommand)); } if (request.CacheProtocol != null && request.CacheProtocol.ProtocolStatus == CacheValidationStatus.DoNotTakeFromCache && request.MethodInfo.Operation == FtpOperation.DownloadFile) commandList.Add(new PipelineEntry(FormatFtpCommand("MDTM", requestFilename))); if (!request.MethodInfo.IsCommandOnly) { // This is why having a protocol logic on the connection is a bad idea if (request.CacheProtocol == null || request.CacheProtocol.ProtocolStatus != CacheValidationStatus.Continue) { if (request.UseBinary) { commandList.Add(new PipelineEntry(FormatFtpCommand("TYPE", "I"))); } else { commandList.Add(new PipelineEntry(FormatFtpCommand("TYPE", "A"))); } if (request.UsePassive) { string passiveCommand = (ServerAddress.AddressFamily == AddressFamily.InterNetwork) ? "PASV" : "EPSV"; commandList.Add(new PipelineEntry(FormatFtpCommand(passiveCommand, null), PipelineEntryFlags.CreateDataConnection)); } else { string portCommand = (ServerAddress.AddressFamily == AddressFamily.InterNetwork) ? "PORT" : "EPRT"; CreateFtpListenerSocket(request); commandList.Add(new PipelineEntry(FormatFtpCommand(portCommand, GetPortCommandLine(request)))); } if (request.CacheProtocol != null && request.CacheProtocol.ProtocolStatus == CacheValidationStatus.CombineCachedAndServerResponse) { // Combining partial cache with the reminder using "REST" if (request.CacheProtocol.Validator.CacheEntry.StreamSize > 0) commandList.Add(new PipelineEntry(FormatFtpCommand("REST", request.CacheProtocol.Validator.CacheEntry.StreamSize.ToString(CultureInfo.InvariantCulture)))); } else if (request.ContentOffset > 0) { // REST command must always be the last sent before the main file command is sent. commandList.Add(new PipelineEntry(FormatFtpCommand("REST", request.ContentOffset.ToString(CultureInfo.InvariantCulture)))); } } else { // revalidating GetFileSize = "SIZE" GetDateTimeStamp = "MDTM" commandList.Add(new PipelineEntry(FormatFtpCommand("SIZE", requestFilename))); commandList.Add(new PipelineEntry(FormatFtpCommand("MDTM", requestFilename))); } } // // Suppress the data file if this is a revalidation request // if (request.CacheProtocol == null || request.CacheProtocol.ProtocolStatus != CacheValidationStatus.Continue) { PipelineEntryFlags flags = PipelineEntryFlags.UserCommand; if (!request.MethodInfo.IsCommandOnly) { flags |= PipelineEntryFlags.GiveDataStream; if (!request.UsePassive) flags |= PipelineEntryFlags.CreateDataConnection; } if (request.MethodInfo.Operation == FtpOperation.Rename) { commandList.Add(new PipelineEntry(FormatFtpCommand("RNFR", requestFilename), flags)); commandList.Add(new PipelineEntry(FormatFtpCommand("RNTO", request.RenameTo), flags)); } else { commandList.Add(new PipelineEntry(FormatFtpCommand(request.Method, requestFilename), flags)); } if (!request.KeepAlive) { commandList.Add(new PipelineEntry(FormatFtpCommand("QUIT", null))); } } return (PipelineEntry []) commandList.ToArray(typeof(PipelineEntry)); }
private void Initialize(bool isServer, string package, NetworkCredential credential, string spn, ContextFlags requestedContextFlags, System.Security.Authentication.ExtendedProtection.ChannelBinding channelBinding) { this.m_TokenSize = SSPIWrapper.GetVerifyPackageInfo(GlobalSSPI.SSPIAuth, package, true).MaxToken; this.m_IsServer = isServer; this.m_Spn = spn; this.m_SecurityContext = null; this.m_RequestedContextFlags = requestedContextFlags; this.m_Package = package; this.m_ChannelBinding = channelBinding; if (credential is SystemNetworkCredential) { this.m_CredentialsHandle = SSPIWrapper.AcquireDefaultCredential(GlobalSSPI.SSPIAuth, package, this.m_IsServer ? CredentialUse.Inbound : CredentialUse.Outbound); this.m_UniqueUserId = "/S"; } else { string userName = credential.InternalGetUserName(); string domain = credential.InternalGetDomain(); AuthIdentity authdata = new AuthIdentity(userName, credential.InternalGetPassword(), ((package == "WDigest") && ((domain == null) || (domain.Length == 0))) ? null : domain); this.m_UniqueUserId = domain + "/" + userName + "/U"; this.m_CredentialsHandle = SSPIWrapper.AcquireCredentialsHandle(GlobalSSPI.SSPIAuth, package, this.m_IsServer ? CredentialUse.Inbound : CredentialUse.Outbound, ref authdata); } }
private Authorization Lookup(HttpWebRequest httpWebRequest, ICredentials credentials) { GlobalLog.Print("BasicClient::Lookup(): ChallengedUri:" + httpWebRequest.ChallengedUri.ToString()); NetworkCredential NC = credentials.GetCredential(httpWebRequest.ChallengedUri, Signature); GlobalLog.Print("BasicClient::Lookup() GetCredential() returns:" + ValidationHelper.ToString(NC)); if (NC == null) { return(null); } ICredentialPolicy policy = AuthenticationManager.CredentialPolicy; if (policy != null && !policy.ShouldSendCredential(httpWebRequest.ChallengedUri, httpWebRequest, NC, this)) { return(null); } string username = NC.InternalGetUserName(); string domain = NC.InternalGetDomain(); if (ValidationHelper.IsBlankString(username)) { return(null); } string rawString = ((!ValidationHelper.IsBlankString(domain)) ? (domain + "\\") : "") + username + ":" + NC.InternalGetPassword(); // The response is an "Authorization:" header where the value is // the text "Basic" followed by BASE64 encoded (as defined by RFC1341) value byte[] bytes = EncodingRightGetBytes(rawString); string responseHeader = BasicClient.AuthType + " " + Convert.ToBase64String(bytes); return(new Authorization(responseHeader, true)); }
private Authorization DoAuthenticate(string challenge, WebRequest webRequest, ICredentials credentials, bool preAuthenticate) { if (credentials == null) { return(null); } HttpWebRequest request = webRequest as HttpWebRequest; NTAuthentication securityContext = null; string incomingBlob = null; if (!preAuthenticate) { int index = AuthenticationManager.FindSubstringNotInQuotes(challenge, Signature); if (index < 0) { return(null); } int startIndex = index + SignatureSize; if ((challenge.Length > startIndex) && (challenge[startIndex] != ',')) { startIndex++; } else { index = -1; } if ((index >= 0) && (challenge.Length > startIndex)) { index = challenge.IndexOf(',', startIndex); if (index != -1) { incomingBlob = challenge.Substring(startIndex, index - startIndex); } else { incomingBlob = challenge.Substring(startIndex); } } securityContext = request.CurrentAuthenticationState.GetSecurityContext(this); } if (securityContext == null) { NetworkCredential credential = credentials.GetCredential(request.ChallengedUri, Signature); string str2 = string.Empty; if ((credential == null) || (!(credential is SystemNetworkCredential) && ((str2 = credential.InternalGetUserName()).Length == 0))) { return(null); } if (((str2.Length + credential.InternalGetPassword().Length) + credential.InternalGetDomain().Length) > 0x20f) { return(null); } ICredentialPolicy credentialPolicy = AuthenticationManager.CredentialPolicy; if ((credentialPolicy != null) && !credentialPolicy.ShouldSendCredential(request.ChallengedUri, request, credential, this)) { return(null); } string computeSpn = request.CurrentAuthenticationState.GetComputeSpn(request); ChannelBinding channelBinding = null; if (request.CurrentAuthenticationState.TransportContext != null) { channelBinding = request.CurrentAuthenticationState.TransportContext.GetChannelBinding(ChannelBindingKind.Endpoint); } securityContext = new NTAuthentication("NTLM", credential, computeSpn, request, channelBinding); request.CurrentAuthenticationState.SetSecurityContext(securityContext, this); } string outgoingBlob = securityContext.GetOutgoingBlob(incomingBlob); if (outgoingBlob == null) { return(null); } bool unsafeOrProxyAuthenticatedConnectionSharing = request.UnsafeOrProxyAuthenticatedConnectionSharing; if (unsafeOrProxyAuthenticatedConnectionSharing) { request.LockConnection = true; } request.NtlmKeepAlive = incomingBlob == null; return(AuthenticationManager.GetGroupAuthorization(this, "NTLM " + outgoingBlob, securityContext.IsCompleted, securityContext, unsafeOrProxyAuthenticatedConnectionSharing, false)); }
internal static Authorization Authenticate(HttpDigestChallenge digestChallenge, NetworkCredential NC, string spn, ChannelBinding binding) { string userName = NC.InternalGetUserName(); if (ValidationHelper.IsBlankString(userName)) { return(null); } string password = NC.InternalGetPassword(); bool flag = IsUpgraded(digestChallenge.Nonce, binding); if (flag) { digestChallenge.ServiceName = spn; digestChallenge.ChannelBinding = hashChannelBinding(binding, digestChallenge.MD5provider); } if (digestChallenge.QopPresent) { if ((digestChallenge.ClientNonce == null) || digestChallenge.Stale) { if (flag) { digestChallenge.ClientNonce = createUpgradedNonce(digestChallenge); } else { digestChallenge.ClientNonce = createNonce(0x20); } digestChallenge.NonceCount = 1; } else { digestChallenge.NonceCount++; } } StringBuilder builder = new StringBuilder(); Charset charset = DetectCharset(userName); if (!digestChallenge.UTF8Charset && (charset == Charset.UTF8)) { return(null); } Charset charset2 = DetectCharset(password); if (!digestChallenge.UTF8Charset && (charset2 == Charset.UTF8)) { return(null); } if (digestChallenge.UTF8Charset) { builder.Append(pair("charset", "utf-8", false)); builder.Append(","); if (charset == Charset.UTF8) { userName = CharsetEncode(userName, Charset.UTF8); builder.Append(pair("username", userName, true)); builder.Append(","); } else { builder.Append(pair("username", CharsetEncode(userName, Charset.UTF8), true)); builder.Append(","); userName = CharsetEncode(userName, charset); } } else { userName = CharsetEncode(userName, charset); builder.Append(pair("username", userName, true)); builder.Append(","); } password = CharsetEncode(password, charset2); builder.Append(pair("realm", digestChallenge.Realm, true)); builder.Append(","); builder.Append(pair("nonce", digestChallenge.Nonce, true)); builder.Append(","); builder.Append(pair("uri", digestChallenge.Uri, true)); if (digestChallenge.QopPresent) { if (digestChallenge.Algorithm != null) { builder.Append(","); builder.Append(pair("algorithm", digestChallenge.Algorithm, true)); } builder.Append(","); builder.Append(pair("cnonce", digestChallenge.ClientNonce, true)); builder.Append(","); builder.Append(pair("nc", digestChallenge.NonceCount.ToString("x8", NumberFormatInfo.InvariantInfo), false)); builder.Append(","); builder.Append(pair("qop", "auth", true)); if (flag) { builder.Append(","); builder.Append(pair("hashed-dirs", "service-name,channel-binding", true)); builder.Append(","); builder.Append(pair("service-name", digestChallenge.ServiceName, true)); builder.Append(","); builder.Append(pair("channel-binding", digestChallenge.ChannelBinding, true)); } } string str3 = responseValue(digestChallenge, userName, password); if (str3 == null) { return(null); } builder.Append(","); builder.Append(pair("response", str3, true)); if (digestChallenge.Opaque != null) { builder.Append(","); builder.Append(pair("opaque", digestChallenge.Opaque, true)); } return(new Authorization("Digest " + builder.ToString(), false)); }