From ff55da9029f8b18343dbf65ca2afa643b6e0877f Mon Sep 17 00:00:00 2001 From: LukePulverenti Date: Wed, 13 Mar 2013 01:19:03 -0400 Subject: [PATCH] switch authentication to sha1 --- MediaBrowser.Api/UserService.cs | 8 +- MediaBrowser.Controller/Entities/User.cs | 24 +-- .../Library/IUserManager.cs | 15 ++ .../Library/UserManager.cs | 51 +++++- MediaBrowser.WebDashboard/ApiClient.js | 11 +- .../Html/scripts/Extensions.js | 173 ++++++++++++++++++ .../Html/scripts/MediaPlayer.js | 2 +- MediaBrowser.WebDashboard/packages.config | 2 +- 8 files changed, 245 insertions(+), 41 deletions(-) diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index 62958fe11..1bb1f2e41 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -228,7 +228,7 @@ namespace MediaBrowser.Api if (!success) { // Unauthorized - throw new ResourceNotFoundException("Invalid user or password entered."); + throw new UnauthorizedAccessException("Invalid user or password entered."); } } @@ -247,7 +247,7 @@ namespace MediaBrowser.Api if (request.ResetPassword) { - var task = user.ResetPassword(_userManager); + var task = _userManager.ResetPassword(user); Task.WaitAll(task); } @@ -257,10 +257,10 @@ namespace MediaBrowser.Api if (!success) { - throw new ResourceNotFoundException("Invalid user or password entered."); + throw new UnauthorizedAccessException("Invalid user or password entered."); } - var task = user.ChangePassword(request.NewPassword, _userManager); + var task = _userManager.ChangePassword(user, request.NewPassword); Task.WaitAll(task); } diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs index 7e50b1ea5..849b9cfee 100644 --- a/MediaBrowser.Controller/Entities/User.cs +++ b/MediaBrowser.Controller/Entities/User.cs @@ -1,15 +1,14 @@ using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Serialization; using System; using System.IO; using System.Linq; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Serialization; namespace MediaBrowser.Controller.Entities { @@ -425,26 +424,5 @@ namespace MediaBrowser.Controller.Entities FileSystem.CopyAll(defaultPath, userPath); } } - - /// - /// Resets the password by clearing it. - /// - /// Task. - public Task ResetPassword(IUserManager userManager) - { - return ChangePassword(string.Empty, userManager); - } - - /// - /// Changes the password. - /// - /// The new password. - /// Task. - public Task ChangePassword(string newPassword, IUserManager userManager) - { - Password = string.IsNullOrEmpty(newPassword) ? string.Empty : newPassword.GetMD5().ToString(); - - return userManager.UpdateUser(this); - } } } diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index cb37b8145..1a2c1482c 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -159,5 +159,20 @@ namespace MediaBrowser.Controller.Library /// The item. /// The data. Task SaveUserDataForItem(User user, BaseItem item, UserItemData data); + + /// + /// Resets the password. + /// + /// The user. + /// Task. + Task ResetPassword(User user); + + /// + /// Changes the password. + /// + /// The user. + /// The new password. + /// Task. + Task ChangePassword(User user, string newPassword); } } diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index a3a24fb34..8928ed238 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -1,4 +1,6 @@ -using MediaBrowser.Common.Events; +using System.Security.Cryptography; +using System.Text; +using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; @@ -185,10 +187,9 @@ namespace MediaBrowser.Server.Implementations.Library throw new ArgumentNullException("user"); } - password = password ?? string.Empty; - var existingPassword = string.IsNullOrEmpty(user.Password) ? string.Empty.GetMD5().ToString() : user.Password; + var existingPasswordString = string.IsNullOrEmpty(user.Password) ? GetSha1String(string.Empty) : user.Password; - var success = password.GetMD5().ToString().Equals(existingPassword); + var success = string.Equals(existingPasswordString, password.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase); // Update LastActivityDate and LastLoginDate, then save if (success) @@ -202,6 +203,20 @@ namespace MediaBrowser.Server.Implementations.Library return success; } + /// + /// Gets the sha1 string. + /// + /// The STR. + /// System.String. + private static string GetSha1String(string str) + { + using (var provider = SHA1.Create()) + { + var hash = provider.ComputeHash(Encoding.UTF8.GetBytes(str)); + return BitConverter.ToString(hash).Replace("-", string.Empty); + } + } + /// /// Logs the user activity. /// @@ -460,6 +475,33 @@ namespace MediaBrowser.Server.Implementations.Library Users = null; } + /// + /// Resets the password by clearing it. + /// + /// Task. + public Task ResetPassword(User user) + { + return ChangePassword(user, string.Empty); + } + + /// + /// Changes the password. + /// + /// The user. + /// The new password. + /// Task. + public Task ChangePassword(User user, string newPassword) + { + if (user == null) + { + throw new ArgumentNullException("user"); + } + + user.Password = string.IsNullOrEmpty(newPassword) ? string.Empty : GetSha1String(newPassword); + + return UpdateUser(user); + } + /// /// Instantiates the new user. /// @@ -475,6 +517,7 @@ namespace MediaBrowser.Server.Implementations.Library DateModified = DateTime.UtcNow }; } + /// /// Used to report that playback has started for an item /// diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js index 31022de38..4081c31e2 100644 --- a/MediaBrowser.WebDashboard/ApiClient.js +++ b/MediaBrowser.WebDashboard/ApiClient.js @@ -1061,11 +1061,8 @@ var ApiClient = { var url = ApiClient.getUrl("Users/" + userId + "/authenticate"); var postData = { + password: SHA1(password || "") }; - - if (password) { - postData.password = password; - } return $.ajax({ type: "POST", @@ -1093,9 +1090,7 @@ var ApiClient = { var postData = { }; - if (currentPassword) { - postData.currentPassword = currentPassword; - } + postData.currentPassword = SHA1(currentPassword); if (newPassword) { postData.newPassword = newPassword; } @@ -1117,7 +1112,7 @@ var ApiClient = { var postData = { }; - postData.resetPassword = 1; + postData.resetPassword = true; return $.post(url, postData); }, diff --git a/MediaBrowser.WebDashboard/Html/scripts/Extensions.js b/MediaBrowser.WebDashboard/Html/scripts/Extensions.js index dba43a704..699ad6143 100644 --- a/MediaBrowser.WebDashboard/Html/scripts/Extensions.js +++ b/MediaBrowser.WebDashboard/Html/scripts/Extensions.js @@ -230,7 +230,180 @@ function parseISO8601Date(s, toLocal) { return new Date(ms); }; +/** +* +* Secure Hash Algorithm (SHA1) +* http://www.webtoolkit.info/ +* +**/ +function SHA1(msg) { + + function rotate_left(n, s) { + var t4 = (n << s) | (n >>> (32 - s)); + return t4; + }; + + function lsb_hex(val) { + var str = ""; + var i; + var vh; + var vl; + + for (i = 0; i <= 6; i += 2) { + vh = (val >>> (i * 4 + 4)) & 0x0f; + vl = (val >>> (i * 4)) & 0x0f; + str += vh.toString(16) + vl.toString(16); + } + return str; + }; + + function cvt_hex(val) { + var str = ""; + var i; + var v; + + for (i = 7; i >= 0; i--) { + v = (val >>> (i * 4)) & 0x0f; + str += v.toString(16); + } + return str; + }; + + + function Utf8Encode(string) { + string = string.replace(/\r\n/g, "\n"); + var utftext = ""; + + for (var n = 0; n < string.length; n++) { + + var c = string.charCodeAt(n); + + if (c < 128) { + utftext += String.fromCharCode(c); + } + else if ((c > 127) && (c < 2048)) { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } + else { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + + } + + return utftext; + }; + + var blockstart; + var i, j; + var W = new Array(80); + var H0 = 0x67452301; + var H1 = 0xEFCDAB89; + var H2 = 0x98BADCFE; + var H3 = 0x10325476; + var H4 = 0xC3D2E1F0; + var A, B, C, D, E; + var temp; + + msg = Utf8Encode(msg); + + var msg_len = msg.length; + + var word_array = new Array(); + for (i = 0; i < msg_len - 3; i += 4) { + j = msg.charCodeAt(i) << 24 | msg.charCodeAt(i + 1) << 16 | + msg.charCodeAt(i + 2) << 8 | msg.charCodeAt(i + 3); + word_array.push(j); + } + + switch (msg_len % 4) { + case 0: + i = 0x080000000; + break; + case 1: + i = msg.charCodeAt(msg_len - 1) << 24 | 0x0800000; + break; + + case 2: + i = msg.charCodeAt(msg_len - 2) << 24 | msg.charCodeAt(msg_len - 1) << 16 | 0x08000; + break; + + case 3: + i = msg.charCodeAt(msg_len - 3) << 24 | msg.charCodeAt(msg_len - 2) << 16 | msg.charCodeAt(msg_len - 1) << 8 | 0x80; + break; + } + + word_array.push(i); + + while ((word_array.length % 16) != 14) word_array.push(0); + + word_array.push(msg_len >>> 29); + word_array.push((msg_len << 3) & 0x0ffffffff); + + + for (blockstart = 0; blockstart < word_array.length; blockstart += 16) { + + for (i = 0; i < 16; i++) W[i] = word_array[blockstart + i]; + for (i = 16; i <= 79; i++) W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); + + A = H0; + B = H1; + C = H2; + D = H3; + E = H4; + + for (i = 0; i <= 19; i++) { + temp = (rotate_left(A, 5) + ((B & C) | (~B & D)) + E + W[i] + 0x5A827999) & 0x0ffffffff; + E = D; + D = C; + C = rotate_left(B, 30); + B = A; + A = temp; + } + + for (i = 20; i <= 39; i++) { + temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff; + E = D; + D = C; + C = rotate_left(B, 30); + B = A; + A = temp; + } + + for (i = 40; i <= 59; i++) { + temp = (rotate_left(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff; + E = D; + D = C; + C = rotate_left(B, 30); + B = A; + A = temp; + } + + for (i = 60; i <= 79; i++) { + temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff; + E = D; + D = C; + C = rotate_left(B, 30); + B = A; + A = temp; + } + + H0 = (H0 + A) & 0x0ffffffff; + H1 = (H1 + B) & 0x0ffffffff; + H2 = (H2 + C) & 0x0ffffffff; + H3 = (H3 + D) & 0x0ffffffff; + H4 = (H4 + E) & 0x0ffffffff; + + } + + var temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4); + + return temp.toLowerCase(); + +} // jqm.page.params.js - version 0.1 // Copyright (c) 2011, Kin Blas diff --git a/MediaBrowser.WebDashboard/Html/scripts/MediaPlayer.js b/MediaBrowser.WebDashboard/Html/scripts/MediaPlayer.js index 4c78d5dfa..928fb06b6 100644 --- a/MediaBrowser.WebDashboard/Html/scripts/MediaPlayer.js +++ b/MediaBrowser.WebDashboard/Html/scripts/MediaPlayer.js @@ -147,9 +147,9 @@ var html = ''; html += '