Merge lp:~mandel/ubuntuone-windows-installer/add_ubuntu_sso_service_keyring into lp:ubuntuone-windows-installer/beta
- add_ubuntu_sso_service_keyring
- Merge into beta
Proposed by
Manuel de la Peña
Status: | Merged |
---|---|
Approved by: | Vincenzo Di Somma |
Approved revision: | 63 |
Merged at revision: | 84 |
Proposed branch: | lp:~mandel/ubuntuone-windows-installer/add_ubuntu_sso_service_keyring |
Merge into: | lp:ubuntuone-windows-installer/beta |
Diff against target: |
1686 lines (+1486/-11) 16 files modified
.bzrignore (+2/-0) main.build (+10/-2) src/Canonical.Ubuntu.SSO.Tests/Canonical.Ubuntu.SSO.Tests.csproj (+74/-0) src/Canonical.Ubuntu.SSO.Tests/KeyringFixture.cs (+409/-0) src/Canonical.Ubuntu.SSO.Tests/Properties/AssemblyInfo.cs (+36/-0) src/Canonical.Ubuntu.SSO/Canonical.Ubuntu.SSO.csproj (+19/-0) src/Canonical.Ubuntu.SSO/DPAPIDataProtector.cs (+65/-0) src/Canonical.Ubuntu.SSO/IDataProtector.cs (+48/-0) src/Canonical.Ubuntu.SSO/IKeyring.cs (+8/-7) src/Canonical.Ubuntu.SSO/IRegistryKey.cs (+171/-0) src/Canonical.Ubuntu.SSO/Keyring.cs (+282/-0) src/Canonical.Ubuntu.SSO/Properties/AssemblyInfo.cs (+1/-2) src/Canonical.Ubuntu.SSO/RegistryKeyWrapper.cs (+261/-0) src/Canonical.UbuntuOne.Common.Tests/Validation/EqualityExtensionsValidation.cs (+38/-0) src/Canonical.UbuntuOne.Common/Validation/EqualityValidationExtensions.cs (+50/-0) src/UbuntuOne.sln (+12/-0) |
To merge this branch: | bzr merge lp:~mandel/ubuntuone-windows-installer/add_ubuntu_sso_service_keyring |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Vincenzo Di Somma (community) | Approve | ||
Rick McBride (community) | Approve | ||
Review via email:
|
Commit message
Description of the change
Adds the implementation of the keyring on windows so that we can securely store the Ubuntu SSO tokens.
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Rick McBride (rmcbride) wrote : | # |
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Rick McBride (rmcbride) wrote : | # |
See above. Looks like something is wrong.
review:
Needs Fixing
- 62. By Manuel de la Peña
-
Merged with trunk.
- 63. By Manuel de la Peña
-
Re-references the NUnit dll.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.bzrignore' | |||
2 | --- .bzrignore 2010-09-08 11:23:58 +0000 | |||
3 | +++ .bzrignore 2010-09-17 16:23:44 +0000 | |||
4 | @@ -8,6 +8,8 @@ | |||
5 | 8 | src/_ReSharper.UbuntuOne | 8 | src/_ReSharper.UbuntuOne |
6 | 9 | src/Canonical.Ubuntu.SSO/bin | 9 | src/Canonical.Ubuntu.SSO/bin |
7 | 10 | src/Canonical.Ubuntu.SSO/obj | 10 | src/Canonical.Ubuntu.SSO/obj |
8 | 11 | src/Canonical.Ubuntu.SSO.Tests/bin | ||
9 | 12 | src/Canonical.Ubuntu.SSO.Tests/obj | ||
10 | 11 | src/Canonical.UbuntuOne.Client/bin | 13 | src/Canonical.UbuntuOne.Client/bin |
11 | 12 | src/Canonical.UbuntuOne.Client/obj | 14 | src/Canonical.UbuntuOne.Client/obj |
12 | 13 | src/Canonical.UbuntuOne.Client.Test/obj | 15 | src/Canonical.UbuntuOne.Client.Test/obj |
13 | 14 | 16 | ||
14 | === modified file 'main.build' | |||
15 | --- main.build 2010-09-02 10:27:49 +0000 | |||
16 | +++ main.build 2010-09-17 16:23:44 +0000 | |||
17 | @@ -156,7 +156,7 @@ | |||
18 | 156 | program="nunit-console.exe" | 156 | program="nunit-console.exe" |
19 | 157 | commandline="Canonical.UbuntuOne.ProcessDispatcher.Tests.dll /xml=../../../../test-results/Canonical.UbuntuOne.ProcessDispatcher.Tests-Result.xml" /> | 157 | commandline="Canonical.UbuntuOne.ProcessDispatcher.Tests.dll /xml=../../../../test-results/Canonical.UbuntuOne.ProcessDispatcher.Tests-Result.xml" /> |
20 | 158 | 158 | ||
22 | 159 | <echo>Canonical.UbuntuOne.Client.Test</echo> | 159 | <echo>Executing Canonical.UbuntuOne.Client.Test</echo> |
23 | 160 | <exec basedir="tools/NUnit" | 160 | <exec basedir="tools/NUnit" |
24 | 161 | managed="true" | 161 | managed="true" |
25 | 162 | workingdir="src/Canonical.UbuntuOne.Client.Test/bin/${enviroment}" | 162 | workingdir="src/Canonical.UbuntuOne.Client.Test/bin/${enviroment}" |
26 | @@ -169,12 +169,20 @@ | |||
27 | 169 | <copy file="src/Canonical.UbuntuOne.Client.Views/bin/${enviroment}/AvalonLibrary.dll" | 169 | <copy file="src/Canonical.UbuntuOne.Client.Views/bin/${enviroment}/AvalonLibrary.dll" |
28 | 170 | tofile="src/UbuntuOneClient.Tests/bin/${enviroment}/AvalonLibrary.dll" /> | 170 | tofile="src/UbuntuOneClient.Tests/bin/${enviroment}/AvalonLibrary.dll" /> |
29 | 171 | 171 | ||
31 | 172 | <echo>UbuntuOneClient.Tests</echo> | 172 | <echo>Executing UbuntuOneClient.Tests</echo> |
32 | 173 | <exec basedir="tools/NUnit" | 173 | <exec basedir="tools/NUnit" |
33 | 174 | managed="true" | 174 | managed="true" |
34 | 175 | workingdir="src/UbuntuOneClient.Tests/bin/${enviroment}" | 175 | workingdir="src/UbuntuOneClient.Tests/bin/${enviroment}" |
35 | 176 | program="nunit-console.exe" | 176 | program="nunit-console.exe" |
36 | 177 | commandline="UbuntuOneClient.Tests.dll /xml=../../../../test-results/UbuntuOneClient.Tests-Result.xml" /> | 177 | commandline="UbuntuOneClient.Tests.dll /xml=../../../../test-results/UbuntuOneClient.Tests-Result.xml" /> |
37 | 178 | |||
38 | 179 | <echo>Executing Canonical.Ubuntu.SSO.Tests</echo> | ||
39 | 180 | <exec basedir="tools/NUnit" | ||
40 | 181 | managed="true" | ||
41 | 182 | workingdir="src/Canonical.Ubuntu.SSO.Tests/bin/${enviroment}" | ||
42 | 183 | program="nunit-console.exe" | ||
43 | 184 | commandline="Canonical.Ubuntu.SSO.Tests.dll /xml=../../../../test-results/Canonical.Ubuntu.SSO.Tests-Result.xml" /> | ||
44 | 185 | |||
45 | 178 | </target> | 186 | </target> |
46 | 179 | <target name="package_python" | 187 | <target name="package_python" |
47 | 180 | description="Creates the exe binary that embeds the python libs that will be used to perform the sync operation in the windows platform"> | 188 | description="Creates the exe binary that embeds the python libs that will be used to perform the sync operation in the windows platform"> |
48 | 181 | 189 | ||
49 | === added directory 'src/Canonical.Ubuntu.SSO.Tests' | |||
50 | === added file 'src/Canonical.Ubuntu.SSO.Tests/Canonical.Ubuntu.SSO.Tests.csproj' | |||
51 | --- src/Canonical.Ubuntu.SSO.Tests/Canonical.Ubuntu.SSO.Tests.csproj 1970-01-01 00:00:00 +0000 | |||
52 | +++ src/Canonical.Ubuntu.SSO.Tests/Canonical.Ubuntu.SSO.Tests.csproj 2010-09-17 16:23:44 +0000 | |||
53 | @@ -0,0 +1,74 @@ | |||
54 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
55 | 2 | <Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
56 | 3 | <PropertyGroup> | ||
57 | 4 | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | ||
58 | 5 | <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | ||
59 | 6 | <ProductVersion>9.0.21022</ProductVersion> | ||
60 | 7 | <SchemaVersion>2.0</SchemaVersion> | ||
61 | 8 | <ProjectGuid>{17BBBEC2-0F4F-48CE-A585-07AA33B6B2B3}</ProjectGuid> | ||
62 | 9 | <OutputType>Library</OutputType> | ||
63 | 10 | <AppDesignerFolder>Properties</AppDesignerFolder> | ||
64 | 11 | <RootNamespace>Canonical.Ubuntu.SSO.Tests</RootNamespace> | ||
65 | 12 | <AssemblyName>Canonical.Ubuntu.SSO.Tests</AssemblyName> | ||
66 | 13 | <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> | ||
67 | 14 | <FileAlignment>512</FileAlignment> | ||
68 | 15 | </PropertyGroup> | ||
69 | 16 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | ||
70 | 17 | <DebugSymbols>true</DebugSymbols> | ||
71 | 18 | <DebugType>full</DebugType> | ||
72 | 19 | <Optimize>false</Optimize> | ||
73 | 20 | <OutputPath>bin\Debug\</OutputPath> | ||
74 | 21 | <DefineConstants>DEBUG;TRACE</DefineConstants> | ||
75 | 22 | <ErrorReport>prompt</ErrorReport> | ||
76 | 23 | <WarningLevel>4</WarningLevel> | ||
77 | 24 | </PropertyGroup> | ||
78 | 25 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | ||
79 | 26 | <DebugType>pdbonly</DebugType> | ||
80 | 27 | <Optimize>true</Optimize> | ||
81 | 28 | <OutputPath>bin\Release\</OutputPath> | ||
82 | 29 | <DefineConstants>TRACE</DefineConstants> | ||
83 | 30 | <ErrorReport>prompt</ErrorReport> | ||
84 | 31 | <WarningLevel>4</WarningLevel> | ||
85 | 32 | </PropertyGroup> | ||
86 | 33 | <ItemGroup> | ||
87 | 34 | <Reference Include="nunit.framework, Version=2.5.5.10112, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL"> | ||
88 | 35 | <SpecificVersion>False</SpecificVersion> | ||
89 | 36 | <HintPath>..\..\lib\Nunit\nunit.framework.dll</HintPath> | ||
90 | 37 | </Reference> | ||
91 | 38 | <Reference Include="Rhino.Mocks, Version=3.6.0.0, Culture=neutral, PublicKeyToken=0b3305902db7183f, processorArchitecture=MSIL"> | ||
92 | 39 | <SpecificVersion>False</SpecificVersion> | ||
93 | 40 | <HintPath>..\..\lib\RhinoMocks\Rhino.Mocks.dll</HintPath> | ||
94 | 41 | </Reference> | ||
95 | 42 | <Reference Include="System" /> | ||
96 | 43 | <Reference Include="System.Core"> | ||
97 | 44 | <RequiredTargetFramework>3.5</RequiredTargetFramework> | ||
98 | 45 | </Reference> | ||
99 | 46 | <Reference Include="System.Security" /> | ||
100 | 47 | <Reference Include="System.Xml.Linq"> | ||
101 | 48 | <RequiredTargetFramework>3.5</RequiredTargetFramework> | ||
102 | 49 | </Reference> | ||
103 | 50 | <Reference Include="System.Data.DataSetExtensions"> | ||
104 | 51 | <RequiredTargetFramework>3.5</RequiredTargetFramework> | ||
105 | 52 | </Reference> | ||
106 | 53 | <Reference Include="System.Data" /> | ||
107 | 54 | <Reference Include="System.Xml" /> | ||
108 | 55 | </ItemGroup> | ||
109 | 56 | <ItemGroup> | ||
110 | 57 | <Compile Include="KeyringFixture.cs" /> | ||
111 | 58 | <Compile Include="Properties\AssemblyInfo.cs" /> | ||
112 | 59 | </ItemGroup> | ||
113 | 60 | <ItemGroup> | ||
114 | 61 | <ProjectReference Include="..\Canonical.Ubuntu.SSO\Canonical.Ubuntu.SSO.csproj"> | ||
115 | 62 | <Project>{9460A771-2589-45DA-9618-9FE8BB7D16E8}</Project> | ||
116 | 63 | <Name>Canonical.Ubuntu.SSO</Name> | ||
117 | 64 | </ProjectReference> | ||
118 | 65 | </ItemGroup> | ||
119 | 66 | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||
120 | 67 | <!-- To modify your build process, add your task inside one of the targets below and uncomment it. | ||
121 | 68 | Other similar extension points exist, see Microsoft.Common.targets. | ||
122 | 69 | <Target Name="BeforeBuild"> | ||
123 | 70 | </Target> | ||
124 | 71 | <Target Name="AfterBuild"> | ||
125 | 72 | </Target> | ||
126 | 73 | --> | ||
127 | 74 | </Project> | ||
128 | 0 | \ No newline at end of file | 75 | \ No newline at end of file |
129 | 1 | 76 | ||
130 | === added file 'src/Canonical.Ubuntu.SSO.Tests/KeyringFixture.cs' | |||
131 | --- src/Canonical.Ubuntu.SSO.Tests/KeyringFixture.cs 1970-01-01 00:00:00 +0000 | |||
132 | +++ src/Canonical.Ubuntu.SSO.Tests/KeyringFixture.cs 2010-09-17 16:23:44 +0000 | |||
133 | @@ -0,0 +1,409 @@ | |||
134 | 1 | /* | ||
135 | 2 | * Copyright 2010 Canonical Ltd. | ||
136 | 3 | * | ||
137 | 4 | * This file is part of UbuntuOne on Windows. | ||
138 | 5 | * | ||
139 | 6 | * UbuntuOne on Windows is free software: you can redistribute it and/or modify | ||
140 | 7 | * it under the terms of the GNU Lesser General Public License version | ||
141 | 8 | * as published by the Free Software Foundation. | ||
142 | 9 | * | ||
143 | 10 | * Ubuntu One on Windows is distributed in the hope that it will be useful, | ||
144 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
145 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
146 | 13 | * GNU Lesser General Public License for more details. | ||
147 | 14 | * | ||
148 | 15 | * You should have received a copy of the GNU Lesser General Public License | ||
149 | 16 | * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>. | ||
150 | 17 | * | ||
151 | 18 | * Authors: Manuel de la Peña <manuel.delapena@canonical.com> | ||
152 | 19 | */ | ||
153 | 20 | using System.Linq; | ||
154 | 21 | using System.Security.Cryptography; | ||
155 | 22 | using System.Text; | ||
156 | 23 | using NUnit.Framework; | ||
157 | 24 | using Rhino.Mocks; | ||
158 | 25 | |||
159 | 26 | namespace Canonical.Ubuntu.SSO.Tests | ||
160 | 27 | { | ||
161 | 28 | [TestFixture] | ||
162 | 29 | public class KeyringFixture | ||
163 | 30 | { | ||
164 | 31 | #region Variables | ||
165 | 32 | |||
166 | 33 | private MockRepository _mocks; | ||
167 | 34 | private IRegistryKey _userRegistry; | ||
168 | 35 | private IRegistryKey _keyringsRoot; | ||
169 | 36 | private IRegistryKey _keyringKey; | ||
170 | 37 | private IDataProtector _dataProtector; | ||
171 | 38 | private Keyring _keyring; | ||
172 | 39 | |||
173 | 40 | #endregion | ||
174 | 41 | |||
175 | 42 | #region Setup & TearDown | ||
176 | 43 | |||
177 | 44 | [SetUp] | ||
178 | 45 | public void Setup() | ||
179 | 46 | { | ||
180 | 47 | _mocks = new MockRepository(); | ||
181 | 48 | _userRegistry = _mocks.StrictMock<IRegistryKey>(); | ||
182 | 49 | _keyringsRoot = _mocks.StrictMock<IRegistryKey>(); | ||
183 | 50 | _keyringKey = _mocks.StrictMock<IRegistryKey>(); | ||
184 | 51 | _dataProtector = _mocks.StrictMock<IDataProtector>(); | ||
185 | 52 | _keyring = new Keyring(_userRegistry) { DataProtector = _dataProtector }; | ||
186 | 53 | } | ||
187 | 54 | |||
188 | 55 | #endregion | ||
189 | 56 | |||
190 | 57 | #region Tests | ||
191 | 58 | |||
192 | 59 | [Test] | ||
193 | 60 | public void DisposeTest() | ||
194 | 61 | { | ||
195 | 62 | using (_mocks.Record()) | ||
196 | 63 | { | ||
197 | 64 | Expect.Call(() => _userRegistry.Dispose()) | ||
198 | 65 | .Repeat.Once(); | ||
199 | 66 | } | ||
200 | 67 | using (_mocks.Playback()) | ||
201 | 68 | { | ||
202 | 69 | // we ensure that we always dispose the registry key to ensure no | ||
203 | 70 | // memory leaks. | ||
204 | 71 | _keyring.Dispose(); | ||
205 | 72 | } | ||
206 | 73 | } | ||
207 | 74 | |||
208 | 75 | [TestCase("Default", "UbuntuOne", "myPassword")] | ||
209 | 76 | [TestCase("Default", "Mandel", "Secret")] | ||
210 | 77 | [TestCase("Test", "Leo", "MySecret")] | ||
211 | 78 | public void CreateSecretNoRootPathPresentTest(string keyringName, string applicationName, string secret) | ||
212 | 79 | { | ||
213 | 80 | using (_mocks.Record()) | ||
214 | 81 | { | ||
215 | 82 | using (_mocks.Ordered()) | ||
216 | 83 | { | ||
217 | 84 | Expect.Call(_userRegistry.GetSubKeyNames()) | ||
218 | 85 | .Return(new[] {"Blah", "BlahBlah"}) | ||
219 | 86 | .Repeat.Twice(); | ||
220 | 87 | |||
221 | 88 | Expect.Call(_userRegistry.CreateSubKey(Keyring.RootPath)) | ||
222 | 89 | .Return(_keyringsRoot) | ||
223 | 90 | .Repeat.Once(); | ||
224 | 91 | |||
225 | 92 | Expect.Call(_keyringsRoot.CreateSubKey(keyringName)) | ||
226 | 93 | .Return(_keyringKey) | ||
227 | 94 | .Repeat.Once(); | ||
228 | 95 | |||
229 | 96 | Expect.Call(() => _keyringKey.Dispose()) | ||
230 | 97 | .Repeat.Any(); | ||
231 | 98 | |||
232 | 99 | Expect.Call(() => _keyringsRoot.Dispose()) | ||
233 | 100 | .Repeat.Any(); | ||
234 | 101 | |||
235 | 102 | Expect.Call(_userRegistry.OpenSubKey(Keyring.RootPath)) | ||
236 | 103 | .Return(_keyringsRoot) | ||
237 | 104 | .Repeat.Once(); | ||
238 | 105 | |||
239 | 106 | Expect.Call(_keyringsRoot.OpenSubKey(keyringName)) | ||
240 | 107 | .Return(_keyringKey) | ||
241 | 108 | .Repeat.Once(); | ||
242 | 109 | |||
243 | 110 | Expect.Call(_dataProtector.Protect(secret, | ||
244 | 111 | Encoding.UTF8.GetBytes(Keyring.Entropy), DataProtectionScope.CurrentUser)) | ||
245 | 112 | .Return(secret) | ||
246 | 113 | .Repeat.Once(); | ||
247 | 114 | |||
248 | 115 | Expect.Call(() => _keyringKey.SetValue(applicationName, secret)) | ||
249 | 116 | .Repeat.Once(); | ||
250 | 117 | |||
251 | 118 | } | ||
252 | 119 | |||
253 | 120 | } | ||
254 | 121 | using (_mocks.Playback()) | ||
255 | 122 | { | ||
256 | 123 | _keyring.CreateSecret(keyringName, applicationName, secret); | ||
257 | 124 | } | ||
258 | 125 | } | ||
259 | 126 | |||
260 | 127 | [TestCase("Default", "UbuntuOne", "myPassword")] | ||
261 | 128 | [TestCase("Default", "Mandel", "Secret")] | ||
262 | 129 | [TestCase("Test", "Leo", "MySecret")] | ||
263 | 130 | public void CreateSecretNoKeyringPresentTest(string keyringName, string applicationName, string secret) | ||
264 | 131 | { | ||
265 | 132 | using (_mocks.Record()) | ||
266 | 133 | { | ||
267 | 134 | using(_mocks.Ordered()) | ||
268 | 135 | { | ||
269 | 136 | Expect.Call(_userRegistry.GetSubKeyNames()) | ||
270 | 137 | .Return(new[] { "Blah", "BlahBlah", Keyring.RootPath}) | ||
271 | 138 | .Repeat.Once(); | ||
272 | 139 | |||
273 | 140 | Expect.Call(() => _keyringsRoot.Dispose()) | ||
274 | 141 | .Repeat.Any(); | ||
275 | 142 | |||
276 | 143 | Expect.Call(_userRegistry.OpenSubKey(Keyring.RootPath)) | ||
277 | 144 | .Return(_keyringsRoot) | ||
278 | 145 | .Repeat.Once(); | ||
279 | 146 | |||
280 | 147 | Expect.Call(_keyringsRoot.GetSubKeyNames()) | ||
281 | 148 | .Return(new string[] { }) | ||
282 | 149 | .Repeat.Once(); | ||
283 | 150 | |||
284 | 151 | Expect.Call(_userRegistry.OpenSubKey(Keyring.RootPath)) | ||
285 | 152 | .Return(_keyringsRoot) | ||
286 | 153 | .Repeat.Once(); | ||
287 | 154 | |||
288 | 155 | Expect.Call(_keyringsRoot.CreateSubKey(keyringName)) | ||
289 | 156 | .Return(_keyringKey) | ||
290 | 157 | .Repeat.Once(); | ||
291 | 158 | |||
292 | 159 | Expect.Call(() => _keyringKey.Dispose()) | ||
293 | 160 | .Repeat.Any(); | ||
294 | 161 | |||
295 | 162 | Expect.Call(_userRegistry.OpenSubKey(Keyring.RootPath)) | ||
296 | 163 | .Return(_keyringsRoot) | ||
297 | 164 | .Repeat.Once(); | ||
298 | 165 | |||
299 | 166 | Expect.Call(_keyringsRoot.OpenSubKey(keyringName)) | ||
300 | 167 | .Return(_keyringKey) | ||
301 | 168 | .Repeat.Once(); | ||
302 | 169 | |||
303 | 170 | Expect.Call(_dataProtector.Protect(secret, | ||
304 | 171 | Encoding.UTF8.GetBytes(Keyring.Entropy), DataProtectionScope.CurrentUser)) | ||
305 | 172 | .Return(secret) | ||
306 | 173 | .Repeat.Once(); | ||
307 | 174 | |||
308 | 175 | Expect.Call(() => _keyringKey.SetValue(applicationName, secret)) | ||
309 | 176 | .Repeat.Once(); | ||
310 | 177 | |||
311 | 178 | } | ||
312 | 179 | } | ||
313 | 180 | using (_mocks.Playback()) | ||
314 | 181 | { | ||
315 | 182 | _keyring.CreateSecret(keyringName, applicationName, secret); | ||
316 | 183 | } | ||
317 | 184 | } | ||
318 | 185 | |||
319 | 186 | [TestCase("Default", "UbuntuOne", "myPassword")] | ||
320 | 187 | [TestCase("Default", "Mandel", "Secret")] | ||
321 | 188 | [TestCase("Test", "Leo", "MySecret")] | ||
322 | 189 | public void CreateSecretPresentKeyringTest(string keyringName, string applicationName, string secret) | ||
323 | 190 | { | ||
324 | 191 | using(_mocks.Record()) | ||
325 | 192 | { | ||
326 | 193 | using(_mocks.Ordered()) | ||
327 | 194 | { | ||
328 | 195 | Expect.Call(_userRegistry.GetSubKeyNames()) | ||
329 | 196 | .Return(new[] { "Blah", "BlahBlah", Keyring.RootPath }) | ||
330 | 197 | .Repeat.Once(); | ||
331 | 198 | |||
332 | 199 | Expect.Call(() => _keyringsRoot.Dispose()) | ||
333 | 200 | .Repeat.Any(); | ||
334 | 201 | |||
335 | 202 | Expect.Call(_userRegistry.OpenSubKey(Keyring.RootPath)) | ||
336 | 203 | .Return(_keyringsRoot) | ||
337 | 204 | .Repeat.Once(); | ||
338 | 205 | |||
339 | 206 | Expect.Call(_keyringsRoot.GetSubKeyNames()) | ||
340 | 207 | .Return(new[] { keyringName}) | ||
341 | 208 | .Repeat.Once(); | ||
342 | 209 | |||
343 | 210 | Expect.Call(() => _keyringKey.Dispose()) | ||
344 | 211 | .Repeat.Any(); | ||
345 | 212 | |||
346 | 213 | Expect.Call(_userRegistry.OpenSubKey(Keyring.RootPath)) | ||
347 | 214 | .Return(_keyringsRoot) | ||
348 | 215 | .Repeat.Once(); | ||
349 | 216 | |||
350 | 217 | Expect.Call(_keyringsRoot.OpenSubKey(keyringName)) | ||
351 | 218 | .Return(_keyringKey) | ||
352 | 219 | .Repeat.Once(); | ||
353 | 220 | |||
354 | 221 | Expect.Call(_dataProtector.Protect(secret, | ||
355 | 222 | Encoding.UTF8.GetBytes(Keyring.Entropy), DataProtectionScope.CurrentUser)) | ||
356 | 223 | .Return(secret) | ||
357 | 224 | .Repeat.Once(); | ||
358 | 225 | |||
359 | 226 | Expect.Call(() => _keyringKey.SetValue(applicationName, secret)) | ||
360 | 227 | .Repeat.Once(); | ||
361 | 228 | } | ||
362 | 229 | } | ||
363 | 230 | using(_mocks.Playback()) | ||
364 | 231 | { | ||
365 | 232 | _keyring.CreateSecret(keyringName, applicationName, secret); | ||
366 | 233 | } | ||
367 | 234 | } | ||
368 | 235 | |||
369 | 236 | [TestCase("Default", "UbuntuOne")] | ||
370 | 237 | [TestCase("Keyring", "AppNAme")] | ||
371 | 238 | public void GetSecretByNameNotKeyringTest(string keyringName, string applicationName) | ||
372 | 239 | { | ||
373 | 240 | using(_mocks.Record()) | ||
374 | 241 | { | ||
375 | 242 | Expect.Call(_userRegistry.GetSubKeyNames()) | ||
376 | 243 | .Return(new[] { "Blah", "BlahBlah" }) | ||
377 | 244 | .Repeat.Once(); | ||
378 | 245 | } | ||
379 | 246 | using(_mocks.Playback()) | ||
380 | 247 | { | ||
381 | 248 | var secret = _keyring.GetSecretByName(keyringName, applicationName); | ||
382 | 249 | Assert.IsEmpty(secret); | ||
383 | 250 | } | ||
384 | 251 | } | ||
385 | 252 | |||
386 | 253 | [TestCase("Default", "UbuntuOne")] | ||
387 | 254 | [TestCase("Keyring", "AppNAme")] | ||
388 | 255 | public void GetSecretByNameKeyringExistsTest(string keyringName, string applicationName) | ||
389 | 256 | { | ||
390 | 257 | using (_mocks.Record()) | ||
391 | 258 | { | ||
392 | 259 | using (_mocks.Ordered()) | ||
393 | 260 | { | ||
394 | 261 | Expect.Call(_userRegistry.GetSubKeyNames()) | ||
395 | 262 | .Return(new[] { "Blah", "BlahBlah", Keyring.RootPath }) | ||
396 | 263 | .Repeat.Once(); | ||
397 | 264 | |||
398 | 265 | Expect.Call(() => _keyringsRoot.Dispose()) | ||
399 | 266 | .Repeat.Any(); | ||
400 | 267 | |||
401 | 268 | Expect.Call(_userRegistry.OpenSubKey(Keyring.RootPath)) | ||
402 | 269 | .Return(_keyringsRoot) | ||
403 | 270 | .Repeat.Once(); | ||
404 | 271 | |||
405 | 272 | Expect.Call(_keyringsRoot.GetSubKeyNames()) | ||
406 | 273 | .Return(new[] { keyringName }) | ||
407 | 274 | .Repeat.Once(); | ||
408 | 275 | |||
409 | 276 | Expect.Call(() => _keyringKey.Dispose()) | ||
410 | 277 | .Repeat.Any(); | ||
411 | 278 | |||
412 | 279 | Expect.Call(_userRegistry.OpenSubKey(Keyring.RootPath)) | ||
413 | 280 | .Return(_keyringsRoot) | ||
414 | 281 | .Repeat.Once(); | ||
415 | 282 | |||
416 | 283 | Expect.Call(_keyringsRoot.OpenSubKey(keyringName)) | ||
417 | 284 | .Return(_keyringKey) | ||
418 | 285 | .Repeat.Once(); | ||
419 | 286 | |||
420 | 287 | Expect.Call(_keyringKey.GetValue(applicationName)) | ||
421 | 288 | .Return(applicationName) | ||
422 | 289 | .Repeat.Once(); | ||
423 | 290 | |||
424 | 291 | Expect.Call(_dataProtector.Unprotect("", | ||
425 | 292 | Encoding.UTF8.GetBytes(Keyring.Entropy), DataProtectionScope.CurrentUser)) | ||
426 | 293 | .IgnoreArguments() | ||
427 | 294 | .Return(applicationName) | ||
428 | 295 | .Repeat.Once(); | ||
429 | 296 | |||
430 | 297 | } | ||
431 | 298 | } | ||
432 | 299 | using (_mocks.Playback()) | ||
433 | 300 | { | ||
434 | 301 | var secret = _keyring.GetSecretByName(keyringName, applicationName); | ||
435 | 302 | Assert.AreEqual(applicationName, secret); | ||
436 | 303 | } | ||
437 | 304 | } | ||
438 | 305 | |||
439 | 306 | [Test] | ||
440 | 307 | public void GetKeyringsTest() | ||
441 | 308 | { | ||
442 | 309 | var keyrings = new[] {"Default", "Test", "Test1"}; | ||
443 | 310 | |||
444 | 311 | using(_mocks.Record()) | ||
445 | 312 | { | ||
446 | 313 | // make it such that the root is present | ||
447 | 314 | Expect.Call(_userRegistry.GetSubKeyNames()) | ||
448 | 315 | .Return(new[] { "Blah", "BlahBlah", Keyring.RootPath }) | ||
449 | 316 | .Repeat.Once(); | ||
450 | 317 | |||
451 | 318 | Expect.Call(() => _keyringsRoot.Dispose()) | ||
452 | 319 | .Repeat.Any(); | ||
453 | 320 | |||
454 | 321 | Expect.Call(_userRegistry.OpenSubKey(Keyring.RootPath)) | ||
455 | 322 | .Return(_keyringsRoot) | ||
456 | 323 | .Repeat.Once(); | ||
457 | 324 | |||
458 | 325 | Expect.Call(_keyringsRoot.GetSubKeyNames()) | ||
459 | 326 | .Return(keyrings) | ||
460 | 327 | .Repeat.Once(); | ||
461 | 328 | |||
462 | 329 | } | ||
463 | 330 | using(_mocks.Playback()) | ||
464 | 331 | { | ||
465 | 332 | Assert.AreSame(_keyring.GetKeyrings(), keyrings); | ||
466 | 333 | } | ||
467 | 334 | } | ||
468 | 335 | |||
469 | 336 | [Test] | ||
470 | 337 | public void GetKeyringsNotRootTest() | ||
471 | 338 | { | ||
472 | 339 | using (_mocks.Record()) | ||
473 | 340 | { | ||
474 | 341 | // make it such that the root is present | ||
475 | 342 | Expect.Call(_userRegistry.GetSubKeyNames()) | ||
476 | 343 | .Return(new[] { "Blah", "BlahBlah"}) | ||
477 | 344 | .Repeat.Once(); | ||
478 | 345 | } | ||
479 | 346 | using (_mocks.Playback()) | ||
480 | 347 | { | ||
481 | 348 | Assert.AreEqual(0, _keyring.GetKeyrings().Count()); | ||
482 | 349 | } | ||
483 | 350 | } | ||
484 | 351 | |||
485 | 352 | [TestCase("Default")] | ||
486 | 353 | [TestCase("Test")] | ||
487 | 354 | public void GetApplicationsTest(string keyringName) | ||
488 | 355 | { | ||
489 | 356 | var applications = new[] {"Ubuntu One", "Test", "Default"}; | ||
490 | 357 | using(_mocks.Record()) | ||
491 | 358 | { | ||
492 | 359 | Expect.Call(_userRegistry.GetSubKeyNames()) | ||
493 | 360 | .Return(new[] { "Blah", "BlahBlah", Keyring.RootPath }) | ||
494 | 361 | .Repeat.Once(); | ||
495 | 362 | |||
496 | 363 | Expect.Call(() => _keyringsRoot.Dispose()) | ||
497 | 364 | .Repeat.Any(); | ||
498 | 365 | |||
499 | 366 | Expect.Call(_userRegistry.OpenSubKey(Keyring.RootPath)) | ||
500 | 367 | .Return(_keyringsRoot) | ||
501 | 368 | .Repeat.Twice(); | ||
502 | 369 | |||
503 | 370 | Expect.Call(_keyringsRoot.GetSubKeyNames()) | ||
504 | 371 | .Return(new[] { keyringName }) | ||
505 | 372 | .Repeat.Once(); | ||
506 | 373 | |||
507 | 374 | Expect.Call(_keyringsRoot.OpenSubKey(keyringName)) | ||
508 | 375 | .Return(_keyringKey) | ||
509 | 376 | .Repeat.Once(); | ||
510 | 377 | |||
511 | 378 | Expect.Call(_keyringKey.GetSubKeyNames()) | ||
512 | 379 | .Return(applications) | ||
513 | 380 | .Repeat.Once(); | ||
514 | 381 | |||
515 | 382 | Expect.Call(() => _keyringKey.Dispose()) | ||
516 | 383 | .Repeat.Any(); | ||
517 | 384 | } | ||
518 | 385 | using(_mocks.Playback()) | ||
519 | 386 | { | ||
520 | 387 | Assert.AreSame(applications, _keyring.GetApplications(keyringName)); | ||
521 | 388 | } | ||
522 | 389 | } | ||
523 | 390 | |||
524 | 391 | [Test] | ||
525 | 392 | public void GetApplicationNotKeyringTest() | ||
526 | 393 | { | ||
527 | 394 | using (_mocks.Record()) | ||
528 | 395 | { | ||
529 | 396 | // make it such that the root is present | ||
530 | 397 | Expect.Call(_userRegistry.GetSubKeyNames()) | ||
531 | 398 | .Return(new[] { "Blah", "BlahBlah" }) | ||
532 | 399 | .Repeat.Once(); | ||
533 | 400 | } | ||
534 | 401 | using(_mocks.Playback()) | ||
535 | 402 | { | ||
536 | 403 | Assert.AreEqual(0, _keyring.GetApplications("Test").Count()); | ||
537 | 404 | } | ||
538 | 405 | } | ||
539 | 406 | |||
540 | 407 | #endregion | ||
541 | 408 | } | ||
542 | 409 | } | ||
543 | 0 | 410 | ||
544 | === added directory 'src/Canonical.Ubuntu.SSO.Tests/Properties' | |||
545 | === added file 'src/Canonical.Ubuntu.SSO.Tests/Properties/AssemblyInfo.cs' | |||
546 | --- src/Canonical.Ubuntu.SSO.Tests/Properties/AssemblyInfo.cs 1970-01-01 00:00:00 +0000 | |||
547 | +++ src/Canonical.Ubuntu.SSO.Tests/Properties/AssemblyInfo.cs 2010-09-17 16:23:44 +0000 | |||
548 | @@ -0,0 +1,36 @@ | |||
549 | 1 | using System.Reflection; | ||
550 | 2 | using System.Runtime.CompilerServices; | ||
551 | 3 | using System.Runtime.InteropServices; | ||
552 | 4 | |||
553 | 5 | // General Information about an assembly is controlled through the following | ||
554 | 6 | // set of attributes. Change these attribute values to modify the information | ||
555 | 7 | // associated with an assembly. | ||
556 | 8 | [assembly: AssemblyTitle("Canonical.Ubuntu.SSO.Tests")] | ||
557 | 9 | [assembly: AssemblyDescription("")] | ||
558 | 10 | [assembly: AssemblyConfiguration("")] | ||
559 | 11 | [assembly: AssemblyCompany("")] | ||
560 | 12 | [assembly: AssemblyProduct("Canonical.Ubuntu.SSO.Tests")] | ||
561 | 13 | [assembly: AssemblyCopyright("Copyright © 2010")] | ||
562 | 14 | [assembly: AssemblyTrademark("")] | ||
563 | 15 | [assembly: AssemblyCulture("")] | ||
564 | 16 | |||
565 | 17 | // Setting ComVisible to false makes the types in this assembly not visible | ||
566 | 18 | // to COM components. If you need to access a type in this assembly from | ||
567 | 19 | // COM, set the ComVisible attribute to true on that type. | ||
568 | 20 | [assembly: ComVisible(false)] | ||
569 | 21 | |||
570 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM | ||
571 | 23 | [assembly: Guid("055a2726-2682-4018-8c48-e1795da59ab2")] | ||
572 | 24 | |||
573 | 25 | // Version information for an assembly consists of the following four values: | ||
574 | 26 | // | ||
575 | 27 | // Major Version | ||
576 | 28 | // Minor Version | ||
577 | 29 | // Build Number | ||
578 | 30 | // Revision | ||
579 | 31 | // | ||
580 | 32 | // You can specify all the values or you can default the Build and Revision Numbers | ||
581 | 33 | // by using the '*' as shown below: | ||
582 | 34 | // [assembly: AssemblyVersion("1.0.*")] | ||
583 | 35 | [assembly: AssemblyVersion("1.0.0.0")] | ||
584 | 36 | [assembly: AssemblyFileVersion("1.0.0.0")] | ||
585 | 0 | 37 | ||
586 | === modified file 'src/Canonical.Ubuntu.SSO/Canonical.Ubuntu.SSO.csproj' | |||
587 | --- src/Canonical.Ubuntu.SSO/Canonical.Ubuntu.SSO.csproj 2010-09-08 11:23:58 +0000 | |||
588 | +++ src/Canonical.Ubuntu.SSO/Canonical.Ubuntu.SSO.csproj 2010-09-17 16:23:44 +0000 | |||
589 | @@ -31,10 +31,15 @@ | |||
590 | 31 | <WarningLevel>4</WarningLevel> | 31 | <WarningLevel>4</WarningLevel> |
591 | 32 | </PropertyGroup> | 32 | </PropertyGroup> |
592 | 33 | <ItemGroup> | 33 | <ItemGroup> |
593 | 34 | <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL"> | ||
594 | 35 | <SpecificVersion>False</SpecificVersion> | ||
595 | 36 | <HintPath>..\..\lib\log4net\log4net.dll</HintPath> | ||
596 | 37 | </Reference> | ||
597 | 34 | <Reference Include="System" /> | 38 | <Reference Include="System" /> |
598 | 35 | <Reference Include="System.Core"> | 39 | <Reference Include="System.Core"> |
599 | 36 | <RequiredTargetFramework>3.5</RequiredTargetFramework> | 40 | <RequiredTargetFramework>3.5</RequiredTargetFramework> |
600 | 37 | </Reference> | 41 | </Reference> |
601 | 42 | <Reference Include="System.Security" /> | ||
602 | 38 | <Reference Include="System.Xml.Linq"> | 43 | <Reference Include="System.Xml.Linq"> |
603 | 39 | <RequiredTargetFramework>3.5</RequiredTargetFramework> | 44 | <RequiredTargetFramework>3.5</RequiredTargetFramework> |
604 | 40 | </Reference> | 45 | </Reference> |
605 | @@ -45,17 +50,31 @@ | |||
606 | 45 | <Reference Include="System.Xml" /> | 50 | <Reference Include="System.Xml" /> |
607 | 46 | </ItemGroup> | 51 | </ItemGroup> |
608 | 47 | <ItemGroup> | 52 | <ItemGroup> |
609 | 53 | <Compile Include="..\Version.cs"> | ||
610 | 54 | <Link>Properties\Version.cs</Link> | ||
611 | 55 | </Compile> | ||
612 | 48 | <Compile Include="CredentialsDeniedEventArgs.cs" /> | 56 | <Compile Include="CredentialsDeniedEventArgs.cs" /> |
613 | 49 | <Compile Include="CredentialsErrorEventArgs.cs" /> | 57 | <Compile Include="CredentialsErrorEventArgs.cs" /> |
614 | 50 | <Compile Include="CredentialsFoundEventArgs.cs" /> | 58 | <Compile Include="CredentialsFoundEventArgs.cs" /> |
615 | 59 | <Compile Include="DPAPIDataProtector.cs" /> | ||
616 | 60 | <Compile Include="IDataProtector.cs" /> | ||
617 | 51 | <Compile Include="ILoginOrRegisterView.cs" /> | 61 | <Compile Include="ILoginOrRegisterView.cs" /> |
618 | 52 | <Compile Include="ILoginView.cs" /> | 62 | <Compile Include="ILoginView.cs" /> |
619 | 63 | <Compile Include="IRegistryKey.cs" /> | ||
620 | 64 | <Compile Include="Keyring.cs" /> | ||
621 | 53 | <Compile Include="LoginCredentialsEventArgs.cs" /> | 65 | <Compile Include="LoginCredentialsEventArgs.cs" /> |
622 | 66 | <Compile Include="RegistryKeyWrapper.cs" /> | ||
623 | 54 | <Compile Include="SSOCredentialsProvider.cs" /> | 67 | <Compile Include="SSOCredentialsProvider.cs" /> |
624 | 55 | <Compile Include="IKeyring.cs" /> | 68 | <Compile Include="IKeyring.cs" /> |
625 | 56 | <Compile Include="ISSOCredentialsProvider.cs" /> | 69 | <Compile Include="ISSOCredentialsProvider.cs" /> |
626 | 57 | <Compile Include="Properties\AssemblyInfo.cs" /> | 70 | <Compile Include="Properties\AssemblyInfo.cs" /> |
627 | 58 | </ItemGroup> | 71 | </ItemGroup> |
628 | 72 | <ItemGroup> | ||
629 | 73 | <ProjectReference Include="..\Canonical.UbuntuOne.Common\Canonical.UbuntuOne.Common.csproj"> | ||
630 | 74 | <Project>{11353FF8-8E5A-488E-9CB1-873DADD232B9}</Project> | ||
631 | 75 | <Name>Canonical.UbuntuOne.Common</Name> | ||
632 | 76 | </ProjectReference> | ||
633 | 77 | </ItemGroup> | ||
634 | 59 | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | 78 | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
635 | 60 | <!-- To modify your build process, add your task inside one of the targets below and uncomment it. | 79 | <!-- To modify your build process, add your task inside one of the targets below and uncomment it. |
636 | 61 | Other similar extension points exist, see Microsoft.Common.targets. | 80 | Other similar extension points exist, see Microsoft.Common.targets. |
637 | 62 | 81 | ||
638 | === added file 'src/Canonical.Ubuntu.SSO/DPAPIDataProtector.cs' | |||
639 | --- src/Canonical.Ubuntu.SSO/DPAPIDataProtector.cs 1970-01-01 00:00:00 +0000 | |||
640 | +++ src/Canonical.Ubuntu.SSO/DPAPIDataProtector.cs 2010-09-17 16:23:44 +0000 | |||
641 | @@ -0,0 +1,65 @@ | |||
642 | 1 | /* | ||
643 | 2 | * Copyright 2010 Canonical Ltd. | ||
644 | 3 | * | ||
645 | 4 | * This file is part of UbuntuOne on Windows. | ||
646 | 5 | * | ||
647 | 6 | * UbuntuOne on Windows is free software: you can redistribute it and/or modify | ||
648 | 7 | * it under the terms of the GNU Lesser General Public License version | ||
649 | 8 | * as published by the Free Software Foundation. | ||
650 | 9 | * | ||
651 | 10 | * Ubuntu One on Windows is distributed in the hope that it will be useful, | ||
652 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
653 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
654 | 13 | * GNU Lesser General Public License for more details. | ||
655 | 14 | * | ||
656 | 15 | * You should have received a copy of the GNU Lesser General Public License | ||
657 | 16 | * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>. | ||
658 | 17 | * | ||
659 | 18 | * Authors: Manuel de la Peña <manuel.delapena@canonical.com> | ||
660 | 19 | */ | ||
661 | 20 | |||
662 | 21 | using System.Security.Cryptography; | ||
663 | 22 | using System.Text; | ||
664 | 23 | |||
665 | 24 | namespace Canonical.Ubuntu.SSO | ||
666 | 25 | { | ||
667 | 26 | /// <summary> | ||
668 | 27 | /// Implementation of the IDataProtector that uses the DAPI api to perform the protection. | ||
669 | 28 | /// </summary> | ||
670 | 29 | public class DPAPIDataProtector : IDataProtector | ||
671 | 30 | { | ||
672 | 31 | #region Implementation of IDataProtector | ||
673 | 32 | |||
674 | 33 | /// <summary> | ||
675 | 34 | /// Protects the userData parameter and returns a string. | ||
676 | 35 | /// </summary> | ||
677 | 36 | /// <param name="userData">A string containing data to protect. </param> | ||
678 | 37 | /// <param name="optionalEntropy">An additional byte array used to encrypt the data. </param> | ||
679 | 38 | /// <param name="scope">One of the DataProtectionScope values.</param> | ||
680 | 39 | /// <returns>A string representing the encrypted data.</returns> | ||
681 | 40 | public string Protect(string userData, byte[] optionalEntropy, DataProtectionScope scope) | ||
682 | 41 | { | ||
683 | 42 | var userDataBytes = Encoding.UTF8.GetBytes(userData); | ||
684 | 43 | var encryptedBytes = ProtectedData.Protect(userDataBytes, optionalEntropy, scope); | ||
685 | 44 | var enc = new UTF8Encoding(false); | ||
686 | 45 | return enc.GetString(encryptedBytes); | ||
687 | 46 | } | ||
688 | 47 | |||
689 | 48 | /// <summary> | ||
690 | 49 | /// Unprotects the encryptedData parameter and returns a string. | ||
691 | 50 | /// </summary> | ||
692 | 51 | /// <param name="encryptedData">A string containing data encrypted using the Protect method.</param> | ||
693 | 52 | /// <param name="optionalEntropy">An additional byte array used to encrypt the data.</param> | ||
694 | 53 | /// <param name="scope">One of the DataProtectionScope values. </param> | ||
695 | 54 | /// <returns>A string representing the unprotected data.</returns> | ||
696 | 55 | public string Unprotect(string encryptedData, byte[] optionalEntropy, DataProtectionScope scope) | ||
697 | 56 | { | ||
698 | 57 | var encryptedDataBytes = Encoding.UTF8.GetBytes(encryptedData); | ||
699 | 58 | var userDataBytes = ProtectedData.Unprotect(encryptedDataBytes, optionalEntropy, scope); | ||
700 | 59 | var enc = new UTF8Encoding(false); | ||
701 | 60 | return enc.GetString(userDataBytes); | ||
702 | 61 | } | ||
703 | 62 | |||
704 | 63 | #endregion | ||
705 | 64 | } | ||
706 | 65 | } | ||
707 | 0 | 66 | ||
708 | === added file 'src/Canonical.Ubuntu.SSO/IDataProtector.cs' | |||
709 | --- src/Canonical.Ubuntu.SSO/IDataProtector.cs 1970-01-01 00:00:00 +0000 | |||
710 | +++ src/Canonical.Ubuntu.SSO/IDataProtector.cs 2010-09-17 16:23:44 +0000 | |||
711 | @@ -0,0 +1,48 @@ | |||
712 | 1 | /* | ||
713 | 2 | * Copyright 2010 Canonical Ltd. | ||
714 | 3 | * | ||
715 | 4 | * This file is part of UbuntuOne on Windows. | ||
716 | 5 | * | ||
717 | 6 | * UbuntuOne on Windows is free software: you can redistribute it and/or modify | ||
718 | 7 | * it under the terms of the GNU Lesser General Public License version | ||
719 | 8 | * as published by the Free Software Foundation. | ||
720 | 9 | * | ||
721 | 10 | * Ubuntu One on Windows is distributed in the hope that it will be useful, | ||
722 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
723 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
724 | 13 | * GNU Lesser General Public License for more details. | ||
725 | 14 | * | ||
726 | 15 | * You should have received a copy of the GNU Lesser General Public License | ||
727 | 16 | * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>. | ||
728 | 17 | * | ||
729 | 18 | * Authors: Manuel de la Peña <manuel.delapena@canonical.com> | ||
730 | 19 | */ | ||
731 | 20 | using System.Security.Cryptography; | ||
732 | 21 | |||
733 | 22 | namespace Canonical.Ubuntu.SSO | ||
734 | 23 | { | ||
735 | 24 | /// <summary> | ||
736 | 25 | /// Interface to be implemented by those objects that are able to encryp and decrypt users | ||
737 | 26 | /// data to protect it. | ||
738 | 27 | /// </summary> | ||
739 | 28 | public interface IDataProtector | ||
740 | 29 | { | ||
741 | 30 | /// <summary> | ||
742 | 31 | /// Protects the userData parameter and returns a string. | ||
743 | 32 | /// </summary> | ||
744 | 33 | /// <param name="userData">A string containing data to protect. </param> | ||
745 | 34 | /// <param name="optionalEntropy">An additional byte array used to encrypt the data. </param> | ||
746 | 35 | /// <param name="scope">One of the DataProtectionScope values.</param> | ||
747 | 36 | /// <returns>A string representing the encrypted data.</returns> | ||
748 | 37 | string Protect(string userData, byte[] optionalEntropy, DataProtectionScope scope); | ||
749 | 38 | |||
750 | 39 | /// <summary> | ||
751 | 40 | /// Unprotects the encryptedData parameter and returns a string. | ||
752 | 41 | /// </summary> | ||
753 | 42 | /// <param name="encryptedData">A string containing data encrypted using the Protect method.</param> | ||
754 | 43 | /// <param name="optionalEntropy">An additional byte array used to encrypt the data.</param> | ||
755 | 44 | /// <param name="scope">One of the DataProtectionScope values. </param> | ||
756 | 45 | /// <returns>A string representing the unprotected data.</returns> | ||
757 | 46 | string Unprotect(string encryptedData, byte[] optionalEntropy, DataProtectionScope scope); | ||
758 | 47 | } | ||
759 | 48 | } | ||
760 | 0 | 49 | ||
761 | === modified file 'src/Canonical.Ubuntu.SSO/IKeyring.cs' | |||
762 | --- src/Canonical.Ubuntu.SSO/IKeyring.cs 2010-09-09 09:11:07 +0000 | |||
763 | +++ src/Canonical.Ubuntu.SSO/IKeyring.cs 2010-09-17 16:23:44 +0000 | |||
764 | @@ -17,6 +17,7 @@ | |||
765 | 17 | * | 17 | * |
766 | 18 | * Authors: Manuel de la Peña <manuel.delapena@canonical.com> | 18 | * Authors: Manuel de la Peña <manuel.delapena@canonical.com> |
767 | 19 | */ | 19 | */ |
768 | 20 | using System; | ||
769 | 20 | using System.Collections.Generic; | 21 | using System.Collections.Generic; |
770 | 21 | 22 | ||
771 | 22 | namespace Canonical.Ubuntu.SSO | 23 | namespace Canonical.Ubuntu.SSO |
772 | @@ -25,7 +26,7 @@ | |||
773 | 25 | /// Interface to be implemented by a class that allows to store data in the registry of the | 26 | /// Interface to be implemented by a class that allows to store data in the registry of the |
774 | 26 | /// current user and makes the class behave like a keyring. | 27 | /// current user and makes the class behave like a keyring. |
775 | 27 | /// </summary> | 28 | /// </summary> |
777 | 28 | public interface IKeyring | 29 | public interface IKeyring : IDisposable |
778 | 29 | { | 30 | { |
779 | 30 | /// <summary> | 31 | /// <summary> |
780 | 31 | /// Creates a new secret in the the keyring with the given name for a given applciation. | 32 | /// Creates a new secret in the the keyring with the given name for a given applciation. |
781 | @@ -36,11 +37,11 @@ | |||
782 | 36 | void CreateSecret(string keyringName, string applicationName, string secret); | 37 | void CreateSecret(string keyringName, string applicationName, string secret); |
783 | 37 | 38 | ||
784 | 38 | /// <summary> | 39 | /// <summary> |
786 | 39 | /// | 40 | /// Gets the secret froma keyring using the name of the application that stored it. |
787 | 40 | /// </summary> | 41 | /// </summary> |
791 | 41 | /// <param name="keyringName"></param> | 42 | /// <param name="keyringName">The name of the keyring where the secret was stored.</param> |
792 | 42 | /// <param name="applicationName"></param> | 43 | /// <param name="applicationName">the name of the application that stored the secret.</param> |
793 | 43 | /// <returns></returns> | 44 | /// <returns>An empty string if the secret does not exist, the secret otherwhise.</returns> |
794 | 44 | string GetSecretByName(string keyringName, string applicationName); | 45 | string GetSecretByName(string keyringName, string applicationName); |
795 | 45 | 46 | ||
796 | 46 | /// <summary> | 47 | /// <summary> |
797 | @@ -52,8 +53,8 @@ | |||
798 | 52 | /// <summary> | 53 | /// <summary> |
799 | 53 | /// Gets a list with all the applications in a keyring. | 54 | /// Gets a list with all the applications in a keyring. |
800 | 54 | /// </summary> | 55 | /// </summary> |
802 | 55 | /// <param name="keyring">The name of the keyring that is queried.</param> | 56 | /// <param name="keyringName">The name of the keyring that is queried.</param> |
803 | 56 | /// <returns>An enumerable with all the applications in the keyring.</returns> | 57 | /// <returns>An enumerable with all the applications in the keyring.</returns> |
805 | 57 | IEnumerable<string> GetApplications(string keyring); | 58 | IEnumerable<string> GetApplications(string keyringName); |
806 | 58 | } | 59 | } |
807 | 59 | } | 60 | } |
808 | 60 | 61 | ||
809 | === added file 'src/Canonical.Ubuntu.SSO/IRegistryKey.cs' | |||
810 | --- src/Canonical.Ubuntu.SSO/IRegistryKey.cs 1970-01-01 00:00:00 +0000 | |||
811 | +++ src/Canonical.Ubuntu.SSO/IRegistryKey.cs 2010-09-17 16:23:44 +0000 | |||
812 | @@ -0,0 +1,171 @@ | |||
813 | 1 | /* | ||
814 | 2 | * Copyright 2010 Canonical Ltd. | ||
815 | 3 | * | ||
816 | 4 | * This file is part of UbuntuOne on Windows. | ||
817 | 5 | * | ||
818 | 6 | * UbuntuOne on Windows is free software: you can redistribute it and/or modify | ||
819 | 7 | * it under the terms of the GNU Lesser General Public License version | ||
820 | 8 | * as published by the Free Software Foundation. | ||
821 | 9 | * | ||
822 | 10 | * Ubuntu One on Windows is distributed in the hope that it will be useful, | ||
823 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
824 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
825 | 13 | * GNU Lesser General Public License for more details. | ||
826 | 14 | * | ||
827 | 15 | * You should have received a copy of the GNU Lesser General Public License | ||
828 | 16 | * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>. | ||
829 | 17 | * | ||
830 | 18 | * Authors: Manuel de la Peña <manuel.delapena@canonical.com> | ||
831 | 19 | */ | ||
832 | 20 | |||
833 | 21 | using System; | ||
834 | 22 | using Microsoft.Win32; | ||
835 | 23 | |||
836 | 24 | namespace Canonical.Ubuntu.SSO | ||
837 | 25 | { | ||
838 | 26 | /// <summary> | ||
839 | 27 | /// Interface that represents a class that allows to perform the access to | ||
840 | 28 | /// the registry keys of the machine. | ||
841 | 29 | /// </summary> | ||
842 | 30 | public interface IRegistryKey : IDisposable | ||
843 | 31 | { | ||
844 | 32 | #region Properties | ||
845 | 33 | |||
846 | 34 | /// <summary> | ||
847 | 35 | /// Retrieves the name of the key. | ||
848 | 36 | /// </summary> | ||
849 | 37 | string Name { get; } | ||
850 | 38 | |||
851 | 39 | /// <summary> | ||
852 | 40 | /// Retrieves the count of subkeys of the current key. | ||
853 | 41 | /// </summary> | ||
854 | 42 | int SubKeyCount { get; } | ||
855 | 43 | |||
856 | 44 | /// <summary> | ||
857 | 45 | /// Retrieves the count of values in the key. | ||
858 | 46 | /// </summary> | ||
859 | 47 | int ValueCount { get; } | ||
860 | 48 | |||
861 | 49 | #endregion | ||
862 | 50 | |||
863 | 51 | #region Methods | ||
864 | 52 | |||
865 | 53 | /// <summary> | ||
866 | 54 | /// Closes the key and flushes it to disk if its contents have been modified. | ||
867 | 55 | /// </summary> | ||
868 | 56 | void Close(); | ||
869 | 57 | |||
870 | 58 | /// <summary> | ||
871 | 59 | /// Creates a new subkey or opens an existing subkey for write access. | ||
872 | 60 | /// The string subkey is not case-sensitive. | ||
873 | 61 | /// </summary> | ||
874 | 62 | /// <param name="name">The name or path of the subkey to create or open. </param> | ||
875 | 63 | /// <returns>A sub key to work with.</returns> | ||
876 | 64 | IRegistryKey CreateSubKey(string name); | ||
877 | 65 | |||
878 | 66 | /// <summary> | ||
879 | 67 | /// Creates a new subkey or opens an existing subkey for write access, using the specified | ||
880 | 68 | /// permission check option. The string subkey is not case-sensitive. | ||
881 | 69 | /// </summary> | ||
882 | 70 | /// <param name="subkey">The name or path of the subkey to create or open.</param> | ||
883 | 71 | /// <param name="permissionCheck">One of the RegistryKeyPermissionCheck values that | ||
884 | 72 | /// specifies whether the key is opened for read or read/write access.</param> | ||
885 | 73 | /// <returns>A subkey to work with.</returns> | ||
886 | 74 | IRegistryKey CreateSubKey(string subkey, RegistryKeyPermissionCheck permissionCheck); | ||
887 | 75 | |||
888 | 76 | /// <summary> | ||
889 | 77 | /// Deletes the specified subkey. The string subkey is not case-sensitive. | ||
890 | 78 | /// </summary> | ||
891 | 79 | /// <param name="subkey">The name of the subkey to delete. </param> | ||
892 | 80 | void DeleteSubKey(string subkey); | ||
893 | 81 | |||
894 | 82 | /// <summary> | ||
895 | 83 | /// Deletes the specified value from this key. | ||
896 | 84 | /// </summary> | ||
897 | 85 | /// <param name="name">The name of the value to delete.</param> | ||
898 | 86 | void DeleteValue(string name); | ||
899 | 87 | |||
900 | 88 | /// <summary> | ||
901 | 89 | /// Writes all the attributes of the specified open registry | ||
902 | 90 | /// key into the registry. | ||
903 | 91 | /// </summary> | ||
904 | 92 | void Flush(); | ||
905 | 93 | |||
906 | 94 | /// <summary> | ||
907 | 95 | /// Retrieves an array of strings that contains all the subkey names. | ||
908 | 96 | /// </summary> | ||
909 | 97 | /// <returns>An array of strings that contains the names of the | ||
910 | 98 | /// subkeys for the current key.</returns> | ||
911 | 99 | string[] GetSubKeyNames(); | ||
912 | 100 | |||
913 | 101 | /// <summary> | ||
914 | 102 | /// Retrieves the value associated with the specified name. | ||
915 | 103 | /// Returns null if the name/value pair does not exist in the registry. | ||
916 | 104 | /// </summary> | ||
917 | 105 | /// <param name="name">The name of the value to retrieve. </param> | ||
918 | 106 | /// <returns>The value associated with name, or null if name is not found.</returns> | ||
919 | 107 | object GetValue(string name); | ||
920 | 108 | |||
921 | 109 | /// <summary> | ||
922 | 110 | /// Retrieves the value associated with the specified name. | ||
923 | 111 | /// If the name is not found, returns the default value that you provide. | ||
924 | 112 | /// </summary> | ||
925 | 113 | /// <param name="name">The name of the value to retrieve.</param> | ||
926 | 114 | /// <param name="defaultValue">The value to return if name does not exist.</param> | ||
927 | 115 | /// <returns>The value associated with name, with any embedded | ||
928 | 116 | /// environment variables left unexpanded, or defaultValue if name is not found.</returns> | ||
929 | 117 | object GetValue(string name, object defaultValue); | ||
930 | 118 | |||
931 | 119 | /// <summary> | ||
932 | 120 | /// Retrieves the registry data type of the value associated with the specified name. | ||
933 | 121 | /// </summary> | ||
934 | 122 | /// <param name="name">The name of the value whose registry data type is to be retrieved. </param> | ||
935 | 123 | /// <returns>A RegistryValueKind value representing the registry | ||
936 | 124 | /// data type of the value associated with name.</returns> | ||
937 | 125 | RegistryValueKind GetValueKind(string name); | ||
938 | 126 | |||
939 | 127 | /// <summary> | ||
940 | 128 | /// Retrieves an array of strings that contains all the | ||
941 | 129 | /// value names associated with this key. | ||
942 | 130 | /// </summary> | ||
943 | 131 | /// <returns>An array of strings that contains | ||
944 | 132 | /// the value names for the current key.</returns> | ||
945 | 133 | string[] GetValueNames(); | ||
946 | 134 | |||
947 | 135 | /// <summary> | ||
948 | 136 | /// Retrieves a subkey as read-only. | ||
949 | 137 | /// </summary> | ||
950 | 138 | /// <param name="name">The name or path of the subkey to open read-only. </param> | ||
951 | 139 | /// <returns>The subkey requested, or null if the operation failed.</returns> | ||
952 | 140 | IRegistryKey OpenSubKey(string name); | ||
953 | 141 | |||
954 | 142 | /// <summary> | ||
955 | 143 | /// Retrieves the specified subkey for read or read/write access. | ||
956 | 144 | /// </summary> | ||
957 | 145 | /// <param name="name">The name or path of the subkey to create or open.</param> | ||
958 | 146 | /// <param name="permissionCheck">One of the RegistryKeyPermissionCheck values | ||
959 | 147 | /// that specifies whether the key is opened for read or read/write access.</param> | ||
960 | 148 | /// <returns></returns> | ||
961 | 149 | IRegistryKey OpenSubKey(string name, RegistryKeyPermissionCheck permissionCheck); | ||
962 | 150 | |||
963 | 151 | /// <summary> | ||
964 | 152 | /// Sets the specified name/value pair. | ||
965 | 153 | /// </summary> | ||
966 | 154 | /// <param name="name">The name of the value to store. </param> | ||
967 | 155 | /// <param name="value">The data to be stored.</param> | ||
968 | 156 | void SetValue(string name, Object value); | ||
969 | 157 | |||
970 | 158 | /// <summary> | ||
971 | 159 | /// Sets the value of a name/value pair in the registry key, using the specified registry data type. | ||
972 | 160 | /// </summary> | ||
973 | 161 | /// <param name="name">The name of the value to be stored. </param> | ||
974 | 162 | /// <param name="value">The data to be stored. </param> | ||
975 | 163 | /// <param name="valueKind">The registry data type to use when storing the data</param> | ||
976 | 164 | void SetValue(string name, Object value, RegistryValueKind valueKind); | ||
977 | 165 | |||
978 | 166 | #endregion | ||
979 | 167 | |||
980 | 168 | |||
981 | 169 | |||
982 | 170 | } | ||
983 | 171 | } | ||
984 | 0 | 172 | ||
985 | === added file 'src/Canonical.Ubuntu.SSO/Keyring.cs' | |||
986 | --- src/Canonical.Ubuntu.SSO/Keyring.cs 1970-01-01 00:00:00 +0000 | |||
987 | +++ src/Canonical.Ubuntu.SSO/Keyring.cs 2010-09-17 16:23:44 +0000 | |||
988 | @@ -0,0 +1,282 @@ | |||
989 | 1 | /* | ||
990 | 2 | * Copyright 2010 Canonical Ltd. | ||
991 | 3 | * | ||
992 | 4 | * This file is part of UbuntuOne on Windows. | ||
993 | 5 | * | ||
994 | 6 | * UbuntuOne on Windows is free software: you can redistribute it and/or modify | ||
995 | 7 | * it under the terms of the GNU Lesser General Public License version | ||
996 | 8 | * as published by the Free Software Foundation. | ||
997 | 9 | * | ||
998 | 10 | * Ubuntu One on Windows is distributed in the hope that it will be useful, | ||
999 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1000 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1001 | 13 | * GNU Lesser General Public License for more details. | ||
1002 | 14 | * | ||
1003 | 15 | * You should have received a copy of the GNU Lesser General Public License | ||
1004 | 16 | * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>. | ||
1005 | 17 | * | ||
1006 | 18 | * Authors: Manuel de la Peña <manuel.delapena@canonical.com> | ||
1007 | 19 | */ | ||
1008 | 20 | using System.Collections.Generic; | ||
1009 | 21 | using System.Linq; | ||
1010 | 22 | using System.Security.Cryptography; | ||
1011 | 23 | using System.Text; | ||
1012 | 24 | using Canonical.UbuntuOne.Common.Validation; | ||
1013 | 25 | using log4net; | ||
1014 | 26 | |||
1015 | 27 | namespace Canonical.Ubuntu.SSO | ||
1016 | 28 | { | ||
1017 | 29 | /// <summary> | ||
1018 | 30 | /// Implementation of the IKeyring interface that will store encripted secrets in the users current keyring. | ||
1019 | 31 | /// </summary> | ||
1020 | 32 | public class Keyring : IKeyring | ||
1021 | 33 | { | ||
1022 | 34 | #region Variables | ||
1023 | 35 | |||
1024 | 36 | internal const string RootPath = "Canonical\\Keyrings"; | ||
1025 | 37 | internal const string Entropy = "bdc97980-bbfa-11df-851a-0800200c9a66"; | ||
1026 | 38 | private const int KeyringMaxNameLength = 255; | ||
1027 | 39 | private ILog _logger; | ||
1028 | 40 | private readonly object _loggerLock = new object(); | ||
1029 | 41 | private bool _keyringsRootExists = false; | ||
1030 | 42 | |||
1031 | 43 | #endregion | ||
1032 | 44 | |||
1033 | 45 | #region DI properties | ||
1034 | 46 | |||
1035 | 47 | /// <summary> | ||
1036 | 48 | /// Gets and sets the users registry key. | ||
1037 | 49 | /// </summary> | ||
1038 | 50 | public IRegistryKey UserRegistry { get; set; } | ||
1039 | 51 | |||
1040 | 52 | /// <summary> | ||
1041 | 53 | /// Gets and sets the data protector to secure the data in the registry. | ||
1042 | 54 | /// </summary> | ||
1043 | 55 | public IDataProtector DataProtector { get; set; } | ||
1044 | 56 | |||
1045 | 57 | #endregion | ||
1046 | 58 | |||
1047 | 59 | #region Properties | ||
1048 | 60 | |||
1049 | 61 | /// <summary> | ||
1050 | 62 | /// Gets and sets the logger that will be used to log the operation of the | ||
1051 | 63 | /// class. | ||
1052 | 64 | /// </summary> | ||
1053 | 65 | public ILog Logger | ||
1054 | 66 | { | ||
1055 | 67 | get | ||
1056 | 68 | { | ||
1057 | 69 | if (_logger == null) | ||
1058 | 70 | { | ||
1059 | 71 | lock (_loggerLock) | ||
1060 | 72 | { | ||
1061 | 73 | _logger = LogManager.GetLogger(typeof(Keyring)); | ||
1062 | 74 | } | ||
1063 | 75 | } | ||
1064 | 76 | return _logger; | ||
1065 | 77 | } | ||
1066 | 78 | set | ||
1067 | 79 | { | ||
1068 | 80 | _logger = value; | ||
1069 | 81 | } | ||
1070 | 82 | } | ||
1071 | 83 | |||
1072 | 84 | #endregion | ||
1073 | 85 | |||
1074 | 86 | #region Constructors | ||
1075 | 87 | |||
1076 | 88 | /// <summary> | ||
1077 | 89 | /// Creates a new instance of the class that will be using the users registry to store the data. | ||
1078 | 90 | /// </summary> | ||
1079 | 91 | public Keyring() | ||
1080 | 92 | : this(new RegistryKeyWrapper()) | ||
1081 | 93 | { | ||
1082 | 94 | |||
1083 | 95 | } | ||
1084 | 96 | |||
1085 | 97 | /// <summary> | ||
1086 | 98 | /// Creates a new instance of the class that will be storing the keyring in the provided registry key. | ||
1087 | 99 | /// </summary> | ||
1088 | 100 | /// <param name="key"></param> | ||
1089 | 101 | public Keyring(IRegistryKey key) | ||
1090 | 102 | { | ||
1091 | 103 | UserRegistry = key; | ||
1092 | 104 | } | ||
1093 | 105 | |||
1094 | 106 | #endregion | ||
1095 | 107 | |||
1096 | 108 | #region Helpers | ||
1097 | 109 | |||
1098 | 110 | private bool KeyringsRootExists() | ||
1099 | 111 | { | ||
1100 | 112 | if (!_keyringsRootExists) | ||
1101 | 113 | { | ||
1102 | 114 | var rootKey = from key in UserRegistry.GetSubKeyNames() | ||
1103 | 115 | where key == RootPath | ||
1104 | 116 | select key; | ||
1105 | 117 | _keyringsRootExists = rootKey.Count() == 1; | ||
1106 | 118 | } | ||
1107 | 119 | return _keyringsRootExists; | ||
1108 | 120 | } | ||
1109 | 121 | |||
1110 | 122 | private bool KeyringExist(string keyring) | ||
1111 | 123 | { | ||
1112 | 124 | // open the root keyring and then the subkeyring to ensure that the | ||
1113 | 125 | // length of the string is not over 255 chars | ||
1114 | 126 | if (!KeyringsRootExists()) | ||
1115 | 127 | return false; | ||
1116 | 128 | |||
1117 | 129 | using (var rootKeyring = UserRegistry.OpenSubKey(RootPath)) | ||
1118 | 130 | { | ||
1119 | 131 | var presentKeyrings = from key in rootKeyring.GetSubKeyNames() | ||
1120 | 132 | where key == keyring | ||
1121 | 133 | select key; | ||
1122 | 134 | return presentKeyrings.Count() == 1; | ||
1123 | 135 | } | ||
1124 | 136 | } | ||
1125 | 137 | |||
1126 | 138 | private IRegistryKey CreateKeyringRootPath() | ||
1127 | 139 | { | ||
1128 | 140 | // create a key with the root path to be used | ||
1129 | 141 | return UserRegistry.CreateSubKey(RootPath); | ||
1130 | 142 | } | ||
1131 | 143 | |||
1132 | 144 | private void CreateKeyring(string keyring) | ||
1133 | 145 | { | ||
1134 | 146 | using(var rootKey = (KeyringsRootExists())? | ||
1135 | 147 | UserRegistry.OpenSubKey(RootPath) : CreateKeyringRootPath()) | ||
1136 | 148 | { | ||
1137 | 149 | var subkey = rootKey.CreateSubKey(keyring); | ||
1138 | 150 | subkey.Dispose(); | ||
1139 | 151 | } | ||
1140 | 152 | } | ||
1141 | 153 | |||
1142 | 154 | private IRegistryKey OpenKeyring(string keyring) | ||
1143 | 155 | { | ||
1144 | 156 | using(var rootKey = UserRegistry.OpenSubKey(RootPath)) | ||
1145 | 157 | { | ||
1146 | 158 | return rootKey.OpenSubKey(keyring); | ||
1147 | 159 | } | ||
1148 | 160 | } | ||
1149 | 161 | |||
1150 | 162 | private void SaveValue(string keyringName, string applicationName, string secret) | ||
1151 | 163 | { | ||
1152 | 164 | using(var keyring = OpenKeyring(keyringName)) | ||
1153 | 165 | { | ||
1154 | 166 | var encryptedSecret = DataProtector.Protect(secret, Encoding.UTF8.GetBytes(Entropy), | ||
1155 | 167 | DataProtectionScope.CurrentUser); | ||
1156 | 168 | keyring.SetValue(applicationName, encryptedSecret); | ||
1157 | 169 | } | ||
1158 | 170 | } | ||
1159 | 171 | |||
1160 | 172 | private string GetValue(string keyringName, string applicationName) | ||
1161 | 173 | { | ||
1162 | 174 | using (var keyring = OpenKeyring(keyringName)) | ||
1163 | 175 | { | ||
1164 | 176 | var secret = keyring.GetValue(applicationName) as string; | ||
1165 | 177 | return DataProtector.Unprotect(secret, Encoding.UTF8.GetBytes(Entropy), DataProtectionScope.CurrentUser); | ||
1166 | 178 | } | ||
1167 | 179 | } | ||
1168 | 180 | |||
1169 | 181 | |||
1170 | 182 | #endregion | ||
1171 | 183 | |||
1172 | 184 | #region Implementation of IKeyring | ||
1173 | 185 | |||
1174 | 186 | /// <summary> | ||
1175 | 187 | /// Creates a new secret in the the keyring with the given name for a given applciation. | ||
1176 | 188 | /// </summary> | ||
1177 | 189 | /// <param name="keyringName">The name of the keyring where the secret will be stored.</param> | ||
1178 | 190 | /// <param name="applicationName">The name of the application whose secret will be stored.</param> | ||
1179 | 191 | /// <param name="secret">The secret to store in the keyring.</param> | ||
1180 | 192 | public void CreateSecret(string keyringName, string applicationName, string secret) | ||
1181 | 193 | { | ||
1182 | 194 | ValidateArgs.Begin() | ||
1183 | 195 | .IsNotNullOrEmpty(keyringName, "keyringName") | ||
1184 | 196 | .IsShorterThan(keyringName, KeyringMaxNameLength, "keyringName") | ||
1185 | 197 | .IsNotNullOrEmpty(applicationName, "applicationName") | ||
1186 | 198 | .IsNotNullOrEmpty(secret, "secret") | ||
1187 | 199 | .Check(); | ||
1188 | 200 | |||
1189 | 201 | if (!KeyringExist(keyringName)) | ||
1190 | 202 | { | ||
1191 | 203 | CreateKeyring(keyringName); | ||
1192 | 204 | Logger.InfoFormat("Creating keyring with name {0}", keyringName); | ||
1193 | 205 | } | ||
1194 | 206 | SaveValue(keyringName, applicationName, secret); | ||
1195 | 207 | } | ||
1196 | 208 | |||
1197 | 209 | /// <summary> | ||
1198 | 210 | /// Gets the secret froma keyring using the name of the application that stored it. | ||
1199 | 211 | /// </summary> | ||
1200 | 212 | /// <param name="keyringName">The name of the keyring where the secret was stored.</param> | ||
1201 | 213 | /// <param name="applicationName">the name of the application that stored the secret.</param> | ||
1202 | 214 | /// <returns>An empty string if the secret does not exist, the secret otherwhise.</returns> | ||
1203 | 215 | public string GetSecretByName(string keyringName, string applicationName) | ||
1204 | 216 | { | ||
1205 | 217 | ValidateArgs.Begin() | ||
1206 | 218 | .IsNotNullOrEmpty(keyringName, "keyringName") | ||
1207 | 219 | .IsShorterThan(keyringName, KeyringMaxNameLength, "keyringName") | ||
1208 | 220 | .IsNotNullOrEmpty(applicationName, "applicationName") | ||
1209 | 221 | .Check(); | ||
1210 | 222 | |||
1211 | 223 | return KeyringExist(keyringName) ? GetValue(keyringName, applicationName) : string.Empty; | ||
1212 | 224 | } | ||
1213 | 225 | |||
1214 | 226 | /// <summary> | ||
1215 | 227 | /// Gets a lists with all the names of the available keyrings. | ||
1216 | 228 | /// </summary> | ||
1217 | 229 | /// <returns>An enumerable with all the names of the different keyrings.</returns> | ||
1218 | 230 | public IEnumerable<string> GetKeyrings() | ||
1219 | 231 | { | ||
1220 | 232 | if(KeyringsRootExists()) | ||
1221 | 233 | { | ||
1222 | 234 | using(var keyringRoot = UserRegistry.OpenSubKey(RootPath)) | ||
1223 | 235 | { | ||
1224 | 236 | return keyringRoot.GetSubKeyNames(); | ||
1225 | 237 | } | ||
1226 | 238 | } | ||
1227 | 239 | return new string[0]; | ||
1228 | 240 | } | ||
1229 | 241 | |||
1230 | 242 | /// <summary> | ||
1231 | 243 | /// Gets a list with all the applications in a keyring. | ||
1232 | 244 | /// </summary> | ||
1233 | 245 | /// <param name="keyringName">The name of the keyring that is queried.</param> | ||
1234 | 246 | /// <returns>An enumerable with all the applications in the keyring.</returns> | ||
1235 | 247 | public IEnumerable<string> GetApplications(string keyringName) | ||
1236 | 248 | { | ||
1237 | 249 | ValidateArgs.Begin() | ||
1238 | 250 | .IsNotNullOrEmpty(keyringName, "keyring") | ||
1239 | 251 | .IsShorterThan(keyringName, KeyringMaxNameLength, "keyring") | ||
1240 | 252 | .Check(); | ||
1241 | 253 | if(KeyringExist(keyringName)) | ||
1242 | 254 | { | ||
1243 | 255 | using(var keyringRoot = UserRegistry.OpenSubKey(RootPath)) | ||
1244 | 256 | { | ||
1245 | 257 | using(var keyring = keyringRoot.OpenSubKey(keyringName)) | ||
1246 | 258 | { | ||
1247 | 259 | return keyring.GetSubKeyNames(); | ||
1248 | 260 | } | ||
1249 | 261 | } | ||
1250 | 262 | } | ||
1251 | 263 | return new string[0]; | ||
1252 | 264 | } | ||
1253 | 265 | |||
1254 | 266 | #endregion | ||
1255 | 267 | |||
1256 | 268 | #region Implementation of IDisposable | ||
1257 | 269 | |||
1258 | 270 | /// <summary> | ||
1259 | 271 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. | ||
1260 | 272 | /// </summary> | ||
1261 | 273 | /// <filterpriority>2</filterpriority> | ||
1262 | 274 | public void Dispose() | ||
1263 | 275 | { | ||
1264 | 276 | if (UserRegistry != null) | ||
1265 | 277 | UserRegistry.Dispose(); | ||
1266 | 278 | } | ||
1267 | 279 | |||
1268 | 280 | #endregion | ||
1269 | 281 | } | ||
1270 | 282 | } | ||
1271 | 0 | 283 | ||
1272 | === modified file 'src/Canonical.Ubuntu.SSO/Properties/AssemblyInfo.cs' | |||
1273 | --- src/Canonical.Ubuntu.SSO/Properties/AssemblyInfo.cs 2010-09-08 11:23:58 +0000 | |||
1274 | +++ src/Canonical.Ubuntu.SSO/Properties/AssemblyInfo.cs 2010-09-17 16:23:44 +0000 | |||
1275 | @@ -32,5 +32,4 @@ | |||
1276 | 32 | // You can specify all the values or you can default the Build and Revision Numbers | 32 | // You can specify all the values or you can default the Build and Revision Numbers |
1277 | 33 | // by using the '*' as shown below: | 33 | // by using the '*' as shown below: |
1278 | 34 | // [assembly: AssemblyVersion("1.0.*")] | 34 | // [assembly: AssemblyVersion("1.0.*")] |
1281 | 35 | [assembly: AssemblyVersion("1.0.0.0")] | 35 | [assembly: InternalsVisibleTo("Canonical.Ubuntu.SSO.Tests")] |
1280 | 36 | [assembly: AssemblyFileVersion("1.0.0.0")] | ||
1282 | 37 | 36 | ||
1283 | === added file 'src/Canonical.Ubuntu.SSO/RegistryKeyWrapper.cs' | |||
1284 | --- src/Canonical.Ubuntu.SSO/RegistryKeyWrapper.cs 1970-01-01 00:00:00 +0000 | |||
1285 | +++ src/Canonical.Ubuntu.SSO/RegistryKeyWrapper.cs 2010-09-17 16:23:44 +0000 | |||
1286 | @@ -0,0 +1,261 @@ | |||
1287 | 1 | /* | ||
1288 | 2 | * Copyright 2010 Canonical Ltd. | ||
1289 | 3 | * | ||
1290 | 4 | * This file is part of UbuntuOne on Windows. | ||
1291 | 5 | * | ||
1292 | 6 | * UbuntuOne on Windows is free software: you can redistribute it and/or modify | ||
1293 | 7 | * it under the terms of the GNU Lesser General Public License version | ||
1294 | 8 | * as published by the Free Software Foundation. | ||
1295 | 9 | * | ||
1296 | 10 | * Ubuntu One on Windows is distributed in the hope that it will be useful, | ||
1297 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1298 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1299 | 13 | * GNU Lesser General Public License for more details. | ||
1300 | 14 | * | ||
1301 | 15 | * You should have received a copy of the GNU Lesser General Public License | ||
1302 | 16 | * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>. | ||
1303 | 17 | * | ||
1304 | 18 | * Authors: Manuel de la Peña <manuel.delapena@canonical.com> | ||
1305 | 19 | */ | ||
1306 | 20 | |||
1307 | 21 | using System; | ||
1308 | 22 | using Microsoft.Win32; | ||
1309 | 23 | |||
1310 | 24 | namespace Canonical.Ubuntu.SSO | ||
1311 | 25 | { | ||
1312 | 26 | /// <summary> | ||
1313 | 27 | /// Simple wrapper around the registry class that allows the class to be mocked for testing | ||
1314 | 28 | /// purposes | ||
1315 | 29 | /// </summary> | ||
1316 | 30 | public class RegistryKeyWrapper : IRegistryKey | ||
1317 | 31 | { | ||
1318 | 32 | #region Variables | ||
1319 | 33 | |||
1320 | 34 | private readonly RegistryKey _key; | ||
1321 | 35 | |||
1322 | 36 | #endregion | ||
1323 | 37 | |||
1324 | 38 | #region Constructors | ||
1325 | 39 | |||
1326 | 40 | /// <summary> | ||
1327 | 41 | /// Creates a new registry key that contains information about the default user configuration. | ||
1328 | 42 | /// </summary> | ||
1329 | 43 | public RegistryKeyWrapper() | ||
1330 | 44 | : this(Registry.Users) | ||
1331 | 45 | { | ||
1332 | 46 | |||
1333 | 47 | } | ||
1334 | 48 | |||
1335 | 49 | /// <summary> | ||
1336 | 50 | /// Creates a new registry key wrapper with the given key. | ||
1337 | 51 | /// </summary> | ||
1338 | 52 | /// <param name="key">The key to be wrapped.</param> | ||
1339 | 53 | public RegistryKeyWrapper(RegistryKey key) | ||
1340 | 54 | { | ||
1341 | 55 | _key = key; | ||
1342 | 56 | } | ||
1343 | 57 | |||
1344 | 58 | #endregion | ||
1345 | 59 | |||
1346 | 60 | #region Implementation of IDisposable | ||
1347 | 61 | |||
1348 | 62 | /// <summary> | ||
1349 | 63 | /// Performs application-defined tasks associated with freeing, releasing, | ||
1350 | 64 | /// or resetting unmanaged resources. | ||
1351 | 65 | /// </summary> | ||
1352 | 66 | /// <filterpriority>2</filterpriority> | ||
1353 | 67 | public void Dispose() | ||
1354 | 68 | { | ||
1355 | 69 | var disposable = (IDisposable)_key; | ||
1356 | 70 | disposable.Dispose(); | ||
1357 | 71 | } | ||
1358 | 72 | |||
1359 | 73 | #endregion | ||
1360 | 74 | |||
1361 | 75 | #region Implementation of IRegistryKey | ||
1362 | 76 | |||
1363 | 77 | /// <summary> | ||
1364 | 78 | /// Retrieves the name of the key. | ||
1365 | 79 | /// </summary> | ||
1366 | 80 | public string Name | ||
1367 | 81 | { | ||
1368 | 82 | get { return _key.Name; } | ||
1369 | 83 | } | ||
1370 | 84 | |||
1371 | 85 | /// <summary> | ||
1372 | 86 | /// Retrieves the count of subkeys of the current key. | ||
1373 | 87 | /// </summary> | ||
1374 | 88 | public int SubKeyCount | ||
1375 | 89 | { | ||
1376 | 90 | get { return _key.SubKeyCount; } | ||
1377 | 91 | } | ||
1378 | 92 | |||
1379 | 93 | /// <summary> | ||
1380 | 94 | /// Retrieves the count of values in the key. | ||
1381 | 95 | /// </summary> | ||
1382 | 96 | public int ValueCount | ||
1383 | 97 | { | ||
1384 | 98 | get { return _key.ValueCount; } | ||
1385 | 99 | } | ||
1386 | 100 | |||
1387 | 101 | /// <summary> | ||
1388 | 102 | /// Closes the key and flushes it to disk if its contents have been modified. | ||
1389 | 103 | /// </summary> | ||
1390 | 104 | public void Close() | ||
1391 | 105 | { | ||
1392 | 106 | _key.Close(); | ||
1393 | 107 | } | ||
1394 | 108 | |||
1395 | 109 | /// <summary> | ||
1396 | 110 | /// Creates a new subkey or opens an existing subkey for write access. | ||
1397 | 111 | /// The string subkey is not case-sensitive. | ||
1398 | 112 | /// </summary> | ||
1399 | 113 | /// <param name="name">The name or path of the subkey to create or open. </param> | ||
1400 | 114 | /// <returns>A sub key to work with.</returns> | ||
1401 | 115 | public IRegistryKey CreateSubKey(string name) | ||
1402 | 116 | { | ||
1403 | 117 | return new RegistryKeyWrapper(_key.CreateSubKey(name)); | ||
1404 | 118 | } | ||
1405 | 119 | |||
1406 | 120 | /// <summary> | ||
1407 | 121 | /// Creates a new subkey or opens an existing subkey for write access, using the specified | ||
1408 | 122 | /// permission check option. The string subkey is not case-sensitive. | ||
1409 | 123 | /// </summary> | ||
1410 | 124 | /// <param name="subkey">The name or path of the subkey to create or open.</param> | ||
1411 | 125 | /// <param name="permissionCheck">One of the RegistryKeyPermissionCheck values that | ||
1412 | 126 | /// specifies whether the key is opened for read or read/write access.</param> | ||
1413 | 127 | /// <returns>A subkey to work with.</returns> | ||
1414 | 128 | public IRegistryKey CreateSubKey(string subkey, RegistryKeyPermissionCheck permissionCheck) | ||
1415 | 129 | { | ||
1416 | 130 | return new RegistryKeyWrapper(_key.CreateSubKey(subkey, permissionCheck)); | ||
1417 | 131 | } | ||
1418 | 132 | |||
1419 | 133 | /// <summary> | ||
1420 | 134 | /// Deletes the specified subkey. The string subkey is not case-sensitive. | ||
1421 | 135 | /// </summary> | ||
1422 | 136 | /// <param name="subkey">The name of the subkey to delete. </param> | ||
1423 | 137 | public void DeleteSubKey(string subkey) | ||
1424 | 138 | { | ||
1425 | 139 | _key.DeleteSubKey(subkey); | ||
1426 | 140 | } | ||
1427 | 141 | |||
1428 | 142 | /// <summary> | ||
1429 | 143 | /// Deletes the specified value from this key. | ||
1430 | 144 | /// </summary> | ||
1431 | 145 | /// <param name="name">The name of the value to delete.</param> | ||
1432 | 146 | public void DeleteValue(string name) | ||
1433 | 147 | { | ||
1434 | 148 | _key.DeleteValue(name); | ||
1435 | 149 | } | ||
1436 | 150 | |||
1437 | 151 | /// <summary> | ||
1438 | 152 | /// Writes all the attributes of the specified open registry | ||
1439 | 153 | /// key into the registry. | ||
1440 | 154 | /// </summary> | ||
1441 | 155 | public void Flush() | ||
1442 | 156 | { | ||
1443 | 157 | _key.Flush(); | ||
1444 | 158 | } | ||
1445 | 159 | |||
1446 | 160 | /// <summary> | ||
1447 | 161 | /// Retrieves an array of strings that contains all the subkey names. | ||
1448 | 162 | /// </summary> | ||
1449 | 163 | /// <returns>An array of strings that contains the names of the | ||
1450 | 164 | /// subkeys for the current key.</returns> | ||
1451 | 165 | public string[] GetSubKeyNames() | ||
1452 | 166 | { | ||
1453 | 167 | return _key.GetSubKeyNames(); | ||
1454 | 168 | } | ||
1455 | 169 | |||
1456 | 170 | /// <summary> | ||
1457 | 171 | /// Retrieves the value associated with the specified name. | ||
1458 | 172 | /// Returns null if the name/value pair does not exist in the registry. | ||
1459 | 173 | /// </summary> | ||
1460 | 174 | /// <param name="name">The name of the value to retrieve. </param> | ||
1461 | 175 | /// <returns>The value associated with name, or null if name is not found.</returns> | ||
1462 | 176 | public object GetValue(string name) | ||
1463 | 177 | { | ||
1464 | 178 | return _key.GetValue(name); | ||
1465 | 179 | } | ||
1466 | 180 | |||
1467 | 181 | /// <summary> | ||
1468 | 182 | /// Retrieves the value associated with the specified name. | ||
1469 | 183 | /// If the name is not found, returns the default value that you provide. | ||
1470 | 184 | /// </summary> | ||
1471 | 185 | /// <param name="name">The name of the value to retrieve.</param> | ||
1472 | 186 | /// <param name="defaultValue">The value to return if name does not exist.</param> | ||
1473 | 187 | /// <returns>The value associated with name, with any embedded | ||
1474 | 188 | /// environment variables left unexpanded, or defaultValue if name is not found.</returns> | ||
1475 | 189 | public object GetValue(string name, object defaultValue) | ||
1476 | 190 | { | ||
1477 | 191 | return _key.GetValue(name, defaultValue); | ||
1478 | 192 | } | ||
1479 | 193 | |||
1480 | 194 | /// <summary> | ||
1481 | 195 | /// Retrieves the registry data type of the value associated with the specified name. | ||
1482 | 196 | /// </summary> | ||
1483 | 197 | /// <param name="name">The name of the value whose registry data type is to be retrieved. </param> | ||
1484 | 198 | /// <returns>A RegistryValueKind value representing the registry | ||
1485 | 199 | /// data type of the value associated with name.</returns> | ||
1486 | 200 | public RegistryValueKind GetValueKind(string name) | ||
1487 | 201 | { | ||
1488 | 202 | return _key.GetValueKind(name); | ||
1489 | 203 | } | ||
1490 | 204 | |||
1491 | 205 | /// <summary> | ||
1492 | 206 | /// Retrieves an array of strings that contains all the | ||
1493 | 207 | /// value names associated with this key. | ||
1494 | 208 | /// </summary> | ||
1495 | 209 | /// <returns>An array of strings that contains | ||
1496 | 210 | /// the value names for the current key.</returns> | ||
1497 | 211 | public string[] GetValueNames() | ||
1498 | 212 | { | ||
1499 | 213 | return _key.GetValueNames(); | ||
1500 | 214 | } | ||
1501 | 215 | |||
1502 | 216 | /// <summary> | ||
1503 | 217 | /// Retrieves a subkey as read-only. | ||
1504 | 218 | /// </summary> | ||
1505 | 219 | /// <param name="name">The name or path of the subkey to open read-only. </param> | ||
1506 | 220 | /// <returns>The subkey requested, or null if the operation failed.</returns> | ||
1507 | 221 | public IRegistryKey OpenSubKey(string name) | ||
1508 | 222 | { | ||
1509 | 223 | return new RegistryKeyWrapper(_key.OpenSubKey(name)); | ||
1510 | 224 | } | ||
1511 | 225 | |||
1512 | 226 | /// <summary> | ||
1513 | 227 | /// Retrieves the specified subkey for read or read/write access. | ||
1514 | 228 | /// </summary> | ||
1515 | 229 | /// <param name="name">The name or path of the subkey to create or open.</param> | ||
1516 | 230 | /// <param name="permissionCheck">One of the RegistryKeyPermissionCheck values | ||
1517 | 231 | /// that specifies whether the key is opened for read or read/write access.</param> | ||
1518 | 232 | /// <returns></returns> | ||
1519 | 233 | public IRegistryKey OpenSubKey(string name, RegistryKeyPermissionCheck permissionCheck) | ||
1520 | 234 | { | ||
1521 | 235 | return new RegistryKeyWrapper(_key.OpenSubKey(name, permissionCheck)); | ||
1522 | 236 | } | ||
1523 | 237 | |||
1524 | 238 | /// <summary> | ||
1525 | 239 | /// Sets the specified name/value pair. | ||
1526 | 240 | /// </summary> | ||
1527 | 241 | /// <param name="name">The name of the value to store. </param> | ||
1528 | 242 | /// <param name="value">The data to be stored.</param> | ||
1529 | 243 | public void SetValue(string name, object value) | ||
1530 | 244 | { | ||
1531 | 245 | _key.SetValue(name, value); | ||
1532 | 246 | } | ||
1533 | 247 | |||
1534 | 248 | /// <summary> | ||
1535 | 249 | /// Sets the value of a name/value pair in the registry key, using the specified registry data type. | ||
1536 | 250 | /// </summary> | ||
1537 | 251 | /// <param name="name">The name of the value to be stored. </param> | ||
1538 | 252 | /// <param name="value">The data to be stored. </param> | ||
1539 | 253 | /// <param name="valueKind">The registry data type to use when storing the data</param> | ||
1540 | 254 | public void SetValue(string name, object value, RegistryValueKind valueKind) | ||
1541 | 255 | { | ||
1542 | 256 | _key.SetValue(name, value, valueKind); | ||
1543 | 257 | } | ||
1544 | 258 | |||
1545 | 259 | #endregion | ||
1546 | 260 | } | ||
1547 | 261 | } | ||
1548 | 0 | 262 | ||
1549 | === modified file 'src/Canonical.UbuntuOne.Common.Tests/Validation/EqualityExtensionsValidation.cs' | |||
1550 | --- src/Canonical.UbuntuOne.Common.Tests/Validation/EqualityExtensionsValidation.cs 2010-07-23 15:50:15 +0000 | |||
1551 | +++ src/Canonical.UbuntuOne.Common.Tests/Validation/EqualityExtensionsValidation.cs 2010-09-17 16:23:44 +0000 | |||
1552 | @@ -236,6 +236,44 @@ | |||
1553 | 236 | .Check(); | 236 | .Check(); |
1554 | 237 | } | 237 | } |
1555 | 238 | 238 | ||
1556 | 239 | [TestCase("Robert", 255)] | ||
1557 | 240 | [TestCase("true", 5)] | ||
1558 | 241 | public void IsShorterThanTest(string value, int length) | ||
1559 | 242 | { | ||
1560 | 243 | ValidateArgs.Begin() | ||
1561 | 244 | .IsShorterThan(value, length, "") | ||
1562 | 245 | .Check(); | ||
1563 | 246 | } | ||
1564 | 247 | |||
1565 | 248 | |||
1566 | 249 | [TestCase("Robert", 2)] | ||
1567 | 250 | [TestCase("true", 1)] | ||
1568 | 251 | [ExpectedException(typeof(ValidationException))] | ||
1569 | 252 | public void IsShorterThanFailTest(string value, int length) | ||
1570 | 253 | { | ||
1571 | 254 | ValidateArgs.Begin() | ||
1572 | 255 | .IsShorterThan(value, length, "") | ||
1573 | 256 | .Check(); | ||
1574 | 257 | } | ||
1575 | 258 | |||
1576 | 259 | [TestCase("true", 4)] | ||
1577 | 260 | [TestCase("Robert", 255)] | ||
1578 | 261 | public void IsShorterOrEqualToTest(string value, int length) | ||
1579 | 262 | { | ||
1580 | 263 | ValidateArgs.Begin() | ||
1581 | 264 | .IsShorterOrEqualTo(value, length, "") | ||
1582 | 265 | .Check(); | ||
1583 | 266 | } | ||
1584 | 267 | |||
1585 | 268 | [TestCase("Robert", 2)] | ||
1586 | 269 | [TestCase("true", 1)] | ||
1587 | 270 | [ExpectedException(typeof(ValidationException))] | ||
1588 | 271 | public void IsShorterOrEqualToFailTest(string value, int length) | ||
1589 | 272 | { | ||
1590 | 273 | ValidateArgs.Begin() | ||
1591 | 274 | .IsShorterOrEqualTo(value, length, "") | ||
1592 | 275 | .Check(); | ||
1593 | 276 | } | ||
1594 | 239 | #endregion | 277 | #endregion |
1595 | 240 | 278 | ||
1596 | 241 | } | 279 | } |
1597 | 242 | 280 | ||
1598 | === modified file 'src/Canonical.UbuntuOne.Common/Validation/EqualityValidationExtensions.cs' | |||
1599 | --- src/Canonical.UbuntuOne.Common/Validation/EqualityValidationExtensions.cs 2010-08-11 08:05:19 +0000 | |||
1600 | +++ src/Canonical.UbuntuOne.Common/Validation/EqualityValidationExtensions.cs 2010-09-17 16:23:44 +0000 | |||
1601 | @@ -242,5 +242,55 @@ | |||
1602 | 242 | (argumentValidation ?? new ArgumentValidation()).AddException(new ArgumentException( | 242 | (argumentValidation ?? new ArgumentValidation()).AddException(new ArgumentException( |
1603 | 243 | string.Format("'{0}' cannot be null or empty.", parameterName))); | 243 | string.Format("'{0}' cannot be null or empty.", parameterName))); |
1604 | 244 | } | 244 | } |
1605 | 245 | |||
1606 | 246 | /// <summary> | ||
1607 | 247 | /// Ensures that the string that was passed as argument is not too long. | ||
1608 | 248 | /// </summary> | ||
1609 | 249 | /// <param name="argumentValidation"> | ||
1610 | 250 | /// A <see cref="ArgumentValidation"/> with the current result of the validations. | ||
1611 | 251 | /// </param> | ||
1612 | 252 | /// <param name="value"> | ||
1613 | 253 | /// A <see cref="System.String"/> with the argument to validate. | ||
1614 | 254 | /// </param> | ||
1615 | 255 | /// <param name="length"> | ||
1616 | 256 | /// An int with the length not to be excided by the string. | ||
1617 | 257 | /// </param> | ||
1618 | 258 | /// <param name="parameterName">The name of the parameter under test.</param> | ||
1619 | 259 | /// <returns> | ||
1620 | 260 | /// A <see cref="ArgumentValidation"/> the result of the validation. | ||
1621 | 261 | /// </returns> | ||
1622 | 262 | public static ArgumentValidation IsShorterThan(this ArgumentValidation argumentValidation, string value, | ||
1623 | 263 | int length, string parameterName) | ||
1624 | 264 | { | ||
1625 | 265 | return (value.Length < length) | ||
1626 | 266 | ? argumentValidation : | ||
1627 | 267 | (argumentValidation ?? new ArgumentValidation()).AddException(new ArgumentException( | ||
1628 | 268 | string.Format("'{0}' has to be smaller than {1} chars.",parameterName, length))); | ||
1629 | 269 | } | ||
1630 | 270 | |||
1631 | 271 | /// <summary> | ||
1632 | 272 | /// Ensures that the string that was passed as argument is not too long. | ||
1633 | 273 | /// </summary> | ||
1634 | 274 | /// <param name="argumentValidation"> | ||
1635 | 275 | /// A <see cref="ArgumentValidation"/> with the current result of the validations. | ||
1636 | 276 | /// </param> | ||
1637 | 277 | /// <param name="value"> | ||
1638 | 278 | /// A <see cref="System.String"/> with the argument to validate. | ||
1639 | 279 | /// </param> | ||
1640 | 280 | /// <param name="length"> | ||
1641 | 281 | /// An int with the length not to be excided by the string. | ||
1642 | 282 | /// </param> | ||
1643 | 283 | /// <param name="parameterName">The name of the parameter under test.</param> | ||
1644 | 284 | /// <returns> | ||
1645 | 285 | /// A <see cref="ArgumentValidation"/> the result of the validation. | ||
1646 | 286 | /// </returns> | ||
1647 | 287 | public static ArgumentValidation IsShorterOrEqualTo(this ArgumentValidation argumentValidation, string value, | ||
1648 | 288 | int length, string parameterName) | ||
1649 | 289 | { | ||
1650 | 290 | return (value.Length <= length) | ||
1651 | 291 | ? argumentValidation : | ||
1652 | 292 | (argumentValidation ?? new ArgumentValidation()).AddException(new ArgumentException( | ||
1653 | 293 | string.Format("'{0}' has to be smaller or equalt to {1} chars.", parameterName, length))); | ||
1654 | 294 | } | ||
1655 | 245 | } | 295 | } |
1656 | 246 | } | 296 | } |
1657 | 247 | 297 | ||
1658 | === modified file 'src/UbuntuOne.sln' | |||
1659 | --- src/UbuntuOne.sln 2010-09-08 11:23:58 +0000 | |||
1660 | +++ src/UbuntuOne.sln 2010-09-17 16:23:44 +0000 | |||
1661 | @@ -25,6 +25,8 @@ | |||
1662 | 25 | EndProject | 25 | EndProject |
1663 | 26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Canonical.Ubuntu.SSO", "Canonical.Ubuntu.SSO\Canonical.Ubuntu.SSO.csproj", "{9460A771-2589-45DA-9618-9FE8BB7D16E8}" | 26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Canonical.Ubuntu.SSO", "Canonical.Ubuntu.SSO\Canonical.Ubuntu.SSO.csproj", "{9460A771-2589-45DA-9618-9FE8BB7D16E8}" |
1664 | 27 | EndProject | 27 | EndProject |
1665 | 28 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Canonical.Ubuntu.SSO.Tests", "Canonical.Ubuntu.SSO.Tests\Canonical.Ubuntu.SSO.Tests.csproj", "{17BBBEC2-0F4F-48CE-A585-07AA33B6B2B3}" | ||
1666 | 29 | EndProject | ||
1667 | 28 | Global | 30 | Global |
1668 | 29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution | 31 | GlobalSection(SolutionConfigurationPlatforms) = preSolution |
1669 | 30 | Debug|Any CPU = Debug|Any CPU | 32 | Debug|Any CPU = Debug|Any CPU |
1670 | @@ -155,6 +157,16 @@ | |||
1671 | 155 | {9460A771-2589-45DA-9618-9FE8BB7D16E8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU | 157 | {9460A771-2589-45DA-9618-9FE8BB7D16E8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU |
1672 | 156 | {9460A771-2589-45DA-9618-9FE8BB7D16E8}.Release|Mixed Platforms.Build.0 = Release|Any CPU | 158 | {9460A771-2589-45DA-9618-9FE8BB7D16E8}.Release|Mixed Platforms.Build.0 = Release|Any CPU |
1673 | 157 | {9460A771-2589-45DA-9618-9FE8BB7D16E8}.Release|x86.ActiveCfg = Release|Any CPU | 159 | {9460A771-2589-45DA-9618-9FE8BB7D16E8}.Release|x86.ActiveCfg = Release|Any CPU |
1674 | 160 | {17BBBEC2-0F4F-48CE-A585-07AA33B6B2B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
1675 | 161 | {17BBBEC2-0F4F-48CE-A585-07AA33B6B2B3}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
1676 | 162 | {17BBBEC2-0F4F-48CE-A585-07AA33B6B2B3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU | ||
1677 | 163 | {17BBBEC2-0F4F-48CE-A585-07AA33B6B2B3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU | ||
1678 | 164 | {17BBBEC2-0F4F-48CE-A585-07AA33B6B2B3}.Debug|x86.ActiveCfg = Debug|Any CPU | ||
1679 | 165 | {17BBBEC2-0F4F-48CE-A585-07AA33B6B2B3}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
1680 | 166 | {17BBBEC2-0F4F-48CE-A585-07AA33B6B2B3}.Release|Any CPU.Build.0 = Release|Any CPU | ||
1681 | 167 | {17BBBEC2-0F4F-48CE-A585-07AA33B6B2B3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU | ||
1682 | 168 | {17BBBEC2-0F4F-48CE-A585-07AA33B6B2B3}.Release|Mixed Platforms.Build.0 = Release|Any CPU | ||
1683 | 169 | {17BBBEC2-0F4F-48CE-A585-07AA33B6B2B3}.Release|x86.ActiveCfg = Release|Any CPU | ||
1684 | 158 | EndGlobalSection | 170 | EndGlobalSection |
1685 | 159 | GlobalSection(SolutionProperties) = preSolution | 171 | GlobalSection(SolutionProperties) = preSolution |
1686 | 160 | HideSolutionNode = FALSE | 172 | HideSolutionNode = FALSE |
I get a whole lot of errors (pasting what I have from my terminal buffer) and the build fails during NAnt.exe tests:
[msbuild] Copying file from "obj\Debug\ ServiceTestApp. pdb" to "bin\Debug\Ser ubuntuone- windows- installer\ revi src\ServiceTest App\ServiceTest App.csproj" (default targets). ubuntuone- windows- installer\ review. aussk\src\ U ubuntuone- windows- installer\ review. a UbuntuOneClient \UbuntuOneClien t.csproj" (13) on node 0 (default targets Resources. resx" into "obj\Deb ent.Properties. Resources. resources" . dCopyLocal: lib\WPFContrib\ AvalonLibrary. dll" to "bin AvalonLibrary. dll". ubuntuone- windows- installer\ review src\Canonical. UbuntuOne. Client\ bin\Debug\ Canonical. UbuntuOne. Client. dll" Canonical. UbuntuOne. Client. dll". ubuntuone- windows- installer\ review src\Canonical. UbuntuOne. Common\ bin\Debug\ Canonical. UbuntuOne. Common. dll" Canonical. UbuntuOne. Common. dll". lib\Spring. Net\Common. Logging. Log4Net. dll Common. Logging. Log4Net. dll". lib\log4net\ log4net. dll" to "bin\Debug\lo ubuntuone- windows- installer\ review src\Canonical. UbuntuOne. Common\ bin\Debug\ Spring. Aop.dll" to "bin\Debug\Sp lib\Spring. Net\Common. Logging. dll" to "bi Common. Logging. dll". ubuntuone- windows- installer\ review src\Canonical. UbuntuOne. Common\ bin\Debug\ DotUpdater. dll" to "bin\Debug\Do ubuntuone- windows- installer\ review src\Canonical. UbuntuOne. Common\ bin\Debug\ Spring. Core.dll" to "bin\Debug\S ubuntuone- windows- installer\ review src\Canonical. UbuntuOne. Common\ bin\Debug\ Spring. Aop.xml" to "bin\Debug\Sp ubuntuone- windows- installer\ review src\Canonical. UbuntuOne. Common\ bin\Debug\ DotUpdater. pdb" to "bin\Debug\Do ubuntuone- windows- installer\ review src\Canonical. UbuntuOne. Common\ bin\Debug\ Spring. Core.xml" to "bin\Debug\S ubuntuone- windows- installer\ review src\Canonical. UbuntuOne. Client\ bin\Debug\ Canonical. UbuntuOne. Client. pdb" Canonical. UbuntuOne. Client. pdb". ubuntuo. ..
viceTestApp.pdb".
[msbuild] Done Building Project "C:\canonical\
ew.aussk\
[msbuild] Project "C:\canonical\
buntuOne.sln" (1) is building "C:\canonical\
ussk\src\
).
[msbuild] Processing 0 EDMX files.
[msbuild] Finished processing 0 EDMX files.
[msbuild] PrepareForBuild:
[msbuild] Creating directory "bin\Debug\".
[msbuild] Creating directory "obj\Debug\".
[msbuild] CoreResGen:
[msbuild] Processing resource file "Properties\
ug\UbuntuOneCli
[msbuild] _CopyFilesMarke
[msbuild] Copying file from "..\..\
\Debug\
[msbuild] Copying file from "C:\canonical\
.aussk\
to "bin\Debug\
[msbuild] Copying file from "C:\canonical\
.aussk\
to "bin\Debug\
[msbuild] Copying file from "..\..\
" to "bin\Debug\
[msbuild] Copying file from "..\..\
g4net.dll".
[msbuild] Copying file from "C:\canonical\
.aussk\
ring.Aop.dll".
[msbuild] Copying file from "..\..\
n\Debug\
[msbuild] Copying file from "C:\canonical\
.aussk\
tUpdater.dll".
[msbuild] Copying file from "C:\canonical\
.aussk\
pring.Core.dll".
[msbuild] Copying file from "C:\canonical\
.aussk\
ring.Aop.xml".
[msbuild] Copying file from "C:\canonical\
.aussk\
tUpdater.pdb".
[msbuild] Copying file from "C:\canonical\
.aussk\
pring.Core.xml".
[msbuild] Copying file from "C:\canonical\
.aussk\
to "bin\Debug\
[msbuild] Copying file from "C:\canonical\