/// <summary> /// Gets the canonicalized resource string for a Blob or Queue service request under the Shared Key authentication scheme. /// </summary> /// <param name="address">The resource URI.</param> /// <param name="accountName">The name of the storage account.</param> /// <returns>The canonicalized resource string.</returns> protected static string GetCanonicalizedResourceVersion2(Uri address, string accountName) { // Resource path StringBuilder resourcepath = new StringBuilder("/"); resourcepath.Append(accountName); // Note that AbsolutePath starts with a '/'. resourcepath.Append(address.AbsolutePath); CanonicalizedString canonicalizedResource = new CanonicalizedString(resourcepath.ToString()); // query parameters NameValueCollection queryVariables = Utilities.ParseQueryString(address.Query); NameValueCollection lowercasedKeyNameValue = new NameValueCollection(); foreach (string key in queryVariables.Keys) { // sort the value and organize it as comma separated values object[] values = queryVariables.GetValues(key); ArrayList sortedValues = new ArrayList(values); sortedValues.Sort(); StringBuilder stringValue = new StringBuilder(); foreach (object value in sortedValues) { if (stringValue.Length > 0) { stringValue.Append(","); } stringValue.Append(value.ToString()); } // key turns out to be null for ?a&b&c&d lowercasedKeyNameValue.Add(key == null ? key : key.ToLowerInvariant(), stringValue.ToString()); } ArrayList sortedKeys = new ArrayList(lowercasedKeyNameValue.AllKeys); sortedKeys.Sort(); foreach (string key in sortedKeys) { StringBuilder queryParamString = new StringBuilder(string.Empty); queryParamString.Append(key); queryParamString.Append(":"); queryParamString.Append(lowercasedKeyNameValue[key]); canonicalizedResource.AppendCanonicalizedElement(queryParamString.ToString()); } return(canonicalizedResource.Value); }
/// <summary> /// Canonicalizes the HTTP request. /// </summary> /// <param name="request">A web request.</param> /// <param name="accountName">The name of the storage account.</param> /// <returns>The canonicalized string for the request.</returns> public override string CanonicalizeHttpRequest(HttpWebRequest request, string accountName) { CanonicalizedString canonicalizedString = new CanonicalizedString(request.Method); string httpContentMD5Value = request.Headers[HttpRequestHeader.ContentMd5]; canonicalizedString.AppendCanonicalizedElement(httpContentMD5Value); string contentType = request.ContentType; canonicalizedString.AppendCanonicalizedElement(contentType); string date = request.Headers[Constants.HeaderConstants.Date]; if (string.IsNullOrEmpty(date)) { string errorMessage = string.Format(CultureInfo.CurrentCulture, SR.MissingXmsDateInHeader); throw new ArgumentException(errorMessage, "request"); } canonicalizedString.AppendCanonicalizedElement(date); canonicalizedString.AppendCanonicalizedElement(GetCanonicalizedResource(request.Address, accountName)); return canonicalizedString.ToString(); }
/// <summary> /// Add x-ms- prefixed headers in a fixed order. /// </summary> /// <param name="headers">The headers.</param> /// <param name="canonicalizedString">The canonicalized string.</param> private static void AddCanonicalizedHeaders(NameValueCollection headers, CanonicalizedString canonicalizedString) { // Look for header names that start with HeaderNames.PrefixForStorageHeader // Then sort them in case-insensitive manner. ArrayList httpStorageHeaderNameArray = new ArrayList(); foreach (string key in headers.Keys) { if (key.ToLowerInvariant().StartsWith(Constants.HeaderConstants.PrefixForStorageHeader, StringComparison.Ordinal)) { httpStorageHeaderNameArray.Add(key.ToLowerInvariant()); } } httpStorageHeaderNameArray.Sort(); // Now go through each header's values in the sorted order and append them to the canonicalized string. foreach (string key in httpStorageHeaderNameArray) { StringBuilder canonicalizedElement = new StringBuilder(key); string delimiter = ":"; ArrayList values = GetHeaderValues(headers, key); // Go through values, unfold them, and then append them to the canonicalized element string. foreach (string value in values) { // Unfolding is simply removal of CRLF. string unfoldedValue = value.Replace("\r\n", string.Empty); // Append it to the canonicalized element string. canonicalizedElement.Append(delimiter); canonicalizedElement.Append(unfoldedValue); delimiter = ","; } // Now, add this canonicalized element to the canonicalized header string. canonicalizedString.AppendCanonicalizedElement(canonicalizedElement.ToString()); } }
/// <summary> /// Constructs a canonicalized string from the request's headers that will be used to construct the signature /// string for signing a Blob or Queue service request under the Shared Key Lite authentication scheme. /// </summary> /// <param name="address">The request URI.</param> /// <param name="accountName">The storage account name.</param> /// <param name="method">The verb to be used for the HTTP request.</param> /// <param name="contentType">The content type of the HTTP request.</param> /// <param name="contentLength">The length of the HTTP request, in bytes.</param> /// <param name="date">The date/time specification for the HTTP request.</param> /// <param name="headers">A collection of additional headers specified on the HTTP request.</param> /// <returns>A canonicalized string.</returns> protected static string CanonicalizeHttpRequestVersion2( Uri address, string accountName, string method, string contentType, long contentLength, string date, NameValueCollection headers) { // The first element should be the Method of the request. // I.e. GET, POST, PUT, or HEAD. CanonicalizedString canonicalizedString = new CanonicalizedString(method); // The next elements are // If any element is missing it may be empty. canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Content-Encoding")); canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Content-Language")); canonicalizedString.AppendCanonicalizedElement(contentLength == -1 ? String.Empty : contentLength.ToString()); canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Content-MD5")); canonicalizedString.AppendCanonicalizedElement(contentType); // If x-ms-date header exists, Date should be empty string canonicalizedString.AppendCanonicalizedElement( GetStandardHeaderValue(headers, Constants.HeaderConstants.Date) != string.Empty ? string.Empty : GetStandardHeaderValue(headers, "Date")); canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-Modified-Since")); canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-Match")); canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-None-Match")); canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-Unmodified-Since")); canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Range")); AddCanonicalizedHeaders(headers, canonicalizedString); AddCanonicalizedResourceVer2(address, accountName, canonicalizedString); return(canonicalizedString.Value); }
protected static string CanonicalizeHttpRequest( Uri address, string accountName, string method, string contentType, string date, NameValueCollection headers) { // The first element should be the Method of the request. // I.e. GET, POST, PUT, or HEAD. CanonicalizedString canonicalizedString = new CanonicalizedString(method); // The second element should be the MD5 value. // This is optional and may be empty. string httpContentMD5Value = string.Empty; // First extract all the content MD5 values from the header. ArrayList httpContentMD5Values = GetHeaderValues(headers, "Content-MD5"); // If we only have one, then set it to the value we want to append to the canonicalized string. if (httpContentMD5Values.Count == 1) { httpContentMD5Value = (string)httpContentMD5Values[0]; } canonicalizedString.AppendCanonicalizedElement(httpContentMD5Value); // The third element should be the content type. canonicalizedString.AppendCanonicalizedElement(contentType); // The fourth element should be the request date. // See if there's an storage date header. // If there's one, then don't use the date header. ArrayList httpStorageDateValues = GetHeaderValues(headers, Constants.HeaderConstants.Date); if (httpStorageDateValues.Count > 0) { date = null; } canonicalizedString.AppendCanonicalizedElement(date); AddCanonicalizedHeaders(headers, canonicalizedString); AddCanonicalizedResource(address, accountName, canonicalizedString); return canonicalizedString.Value; }
/// <summary> /// Add the resource name. /// </summary> /// <param name="address">The address.</param> /// <param name="accountName">Name of the account.</param> /// <param name="canonicalizedString">The canonicalized string.</param> private static void AddCanonicalizedResource(Uri address, string accountName, CanonicalizedString canonicalizedString) { // Now we append the canonicalized resource element. string canonicalizedResource = GetCanonicalizedResource(address, accountName); canonicalizedString.AppendCanonicalizedElement(canonicalizedResource); }
/// <summary> /// Gets the canonicalized resource string for a Blob or Queue service request under the Shared Key authentication scheme. /// </summary> /// <param name="address">The resource URI.</param> /// <param name="accountName">The name of the storage account.</param> /// <returns>The canonicalized resource string.</returns> protected static string GetCanonicalizedResourceVersion2(Uri address, string accountName) { // Resource path StringBuilder resourcepath = new StringBuilder("/"); resourcepath.Append(accountName); // Note that AbsolutePath starts with a '/'. resourcepath.Append(address.AbsolutePath); CanonicalizedString canonicalizedResource = new CanonicalizedString(resourcepath.ToString()); // query parameters NameValueCollection queryVariables = HttpUtility.ParseQueryString(address.Query); NameValueCollection lowercasedKeyNameValue = new NameValueCollection(); foreach (string key in queryVariables.Keys) { // sort the value and organize it as comma separated values object[] values = queryVariables.GetValues(key); ArrayList sortedValues = new ArrayList(values); sortedValues.Sort(); StringBuilder stringValue = new StringBuilder(); foreach (object value in sortedValues) { if (stringValue.Length > 0) { stringValue.Append(","); } stringValue.Append(value.ToString()); } // key turns out to be null for ?a&b&c&d lowercasedKeyNameValue.Add(key == null ? key : key.ToLowerInvariant(), stringValue.ToString()); } ArrayList sortedKeys = new ArrayList(lowercasedKeyNameValue.AllKeys); sortedKeys.Sort(); foreach (string key in sortedKeys) { StringBuilder queryParamString = new StringBuilder(string.Empty); queryParamString.Append(key); queryParamString.Append(":"); queryParamString.Append(lowercasedKeyNameValue[key]); canonicalizedResource.AppendCanonicalizedElement(queryParamString.ToString()); } return canonicalizedResource.Value; }
/// <summary> /// Constructs a canonicalized string from the request's headers that will be used to construct the signature /// string for signing a Blob or Queue service request under the Shared Key Lite authentication scheme. /// </summary> /// <param name="address">The request URI.</param> /// <param name="accountName">The storage account name.</param> /// <param name="method">The verb to be used for the HTTP request.</param> /// <param name="contentType">The content type of the HTTP request.</param> /// <param name="contentLength">The length of the HTTP request, in bytes.</param> /// <param name="date">The date/time specification for the HTTP request.</param> /// <param name="headers">A collection of additional headers specified on the HTTP request.</param> /// <returns>A canonicalized string.</returns> protected static string CanonicalizeHttpRequestVersion2( Uri address, string accountName, string method, string contentType, long contentLength, string date, NameValueCollection headers) { // The first element should be the Method of the request. // I.e. GET, POST, PUT, or HEAD. CanonicalizedString canonicalizedString = new CanonicalizedString(method); // The next elements are // If any element is missing it may be empty. canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Content-Encoding")); canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Content-Language")); canonicalizedString.AppendCanonicalizedElement(contentLength == -1 ? String.Empty : contentLength.ToString()); canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Content-MD5")); canonicalizedString.AppendCanonicalizedElement(contentType); // If x-ms-date header exists, Date should be empty string canonicalizedString.AppendCanonicalizedElement( GetStandardHeaderValue(headers, Constants.HeaderConstants.Date) != string.Empty ? string.Empty : GetStandardHeaderValue(headers, "Date")); canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-Modified-Since")); canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-Match")); canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-None-Match")); canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-Unmodified-Since")); canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Range")); AddCanonicalizedHeaders(headers, canonicalizedString); AddCanonicalizedResourceVer2(address, accountName, canonicalizedString); return canonicalizedString.Value; }