├── .gitignore
├── COPYING
├── README.md
├── img
├── adbl.png
└── help.png
├── maclocker.sln
└── maclocker
├── App.config
├── Program.cs
├── Properties
└── AssemblyInfo.cs
└── maclocker.csproj
/.gitignore:
--------------------------------------------------------------------------------
1 | *.suo
2 | *.user
3 | maclocker/bin/*
4 | maclocker/obj/*
5 |
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Berke Viktor
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MacLocker
2 |
3 | ## What is it
4 |
5 | It's a utility to save FileVault recovery keys as BitLocker passwords in Active Directory
6 |
7 | ## Usage
8 |
9 |
10 |
11 | ## Result
12 |
13 |
14 |
--------------------------------------------------------------------------------
/img/adbl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bviktor/maclocker/453ae08821079c48c505aa4973604fb9ffac0feb/img/adbl.png
--------------------------------------------------------------------------------
/img/help.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bviktor/maclocker/453ae08821079c48c505aa4973604fb9ffac0feb/img/help.png
--------------------------------------------------------------------------------
/maclocker.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.31101.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "maclocker", "maclocker\maclocker.csproj", "{5871F3FB-F2CD-44E5-B449-03B31448BA70}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {5871F3FB-F2CD-44E5-B449-03B31448BA70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {5871F3FB-F2CD-44E5-B449-03B31448BA70}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {5871F3FB-F2CD-44E5-B449-03B31448BA70}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {5871F3FB-F2CD-44E5-B449-03B31448BA70}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/maclocker/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/maclocker/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.DirectoryServices;
7 | using System.Configuration;
8 |
9 | namespace maclocker
10 | {
11 | class Program
12 | {
13 | public static String GenerateDateString()
14 | {
15 | DateTime date = DateTime.Now;
16 | return date.ToString("yyyy-MM-ddTHH:mm:ss\\\\K");
17 | }
18 |
19 | public static String GenerateGuid(int mode)
20 | {
21 | Guid guid = Guid.NewGuid();
22 |
23 | switch (mode)
24 | {
25 | case 1:
26 | return guid.ToString("D");
27 |
28 | case 2:
29 | string guidString = guid.ToString("N");
30 | char[] guidChar = guidString.ToCharArray();
31 | String buf = "";
32 |
33 | for (int i = 0; i < 32; i++)
34 | {
35 | buf += "0x" + guidChar[i] + guidChar[++i] + " ";
36 | }
37 |
38 | return buf;
39 |
40 | case 3:
41 | return guid.ToString("N");
42 |
43 | default:
44 | return "";
45 | }
46 | }
47 |
48 | public static String GenerateKeyCN()
49 | {
50 | return GenerateDateString() + "{" + GenerateGuid(1) + "}";
51 | }
52 |
53 | public static bool ComputerExists(String ouPath, String objName)
54 | {
55 | if (DirectoryEntry.Exists("LDAP://CN=" + objName + "," + ouPath))
56 | {
57 | return true;
58 | }
59 | else
60 | {
61 | return false;
62 | }
63 | }
64 |
65 | public static bool CreateComputer(String ouPath, String objName, bool useOsAuth, String adminUser, String adminPass)
66 | {
67 | try
68 | {
69 | DirectoryEntry comp;
70 |
71 | if (useOsAuth)
72 | {
73 | comp = new DirectoryEntry("LDAP://" + ouPath);
74 | }
75 | else
76 | {
77 | comp = new DirectoryEntry("LDAP://" + ouPath, adminUser, adminPass);
78 | }
79 |
80 | DirectoryEntry group = comp.Children.Add("CN=" + objName, "computer");
81 | group.Properties["sAmAccountName"].Value = objName;
82 | group.CommitChanges();
83 | return true;
84 | }
85 | catch (Exception e)
86 | {
87 | Console.WriteLine(e.ToString());
88 | return false;
89 | }
90 | }
91 |
92 | public static bool AddRecoveryKey(String ouPath, String objName, String recoveryPassword, bool useOsAuth, String adminUser, String adminPass)
93 | {
94 | try
95 | {
96 | DirectoryEntry comp;
97 |
98 | if (useOsAuth)
99 | {
100 | comp = new DirectoryEntry("LDAP://CN=" + objName + "," + ouPath);
101 | }
102 | else
103 | {
104 | comp = new DirectoryEntry("LDAP://CN=" + objName + "," + ouPath, adminUser, adminPass);
105 | }
106 |
107 | DirectoryEntry recKey = comp.Children.Add("CN=" + GenerateKeyCN(), "msFVE-RecoveryInformation");
108 | recKey.Properties["msFVE-RecoveryPassword"].Value = recoveryPassword;
109 | recKey.Properties["msFVE-RecoveryGuid"].Value = GenerateGuid(2);
110 | recKey.CommitChanges();
111 | return true;
112 | }
113 | catch (Exception e)
114 | {
115 | Console.WriteLine(e.ToString());
116 | return false;
117 | }
118 | }
119 |
120 | public static void WriteDashes()
121 | {
122 | Console.Write("--------------------------------------------------------------------------------");
123 | }
124 |
125 | public static void FinishUp()
126 | {
127 | WriteDashes();
128 | Console.WriteLine("End of execution, press any key to close...");
129 | Console.ReadKey(true);
130 | }
131 |
132 | static void PrintHelp()
133 | {
134 | Console.WriteLine("MacLocker - utility to save FileVault recovery keys as BitLocker passwords in Active Directory. Requires your AD schema to be prepared to store BitLocker info.");
135 | Console.WriteLine();
136 | Console.WriteLine("Usage:");
137 | Console.WriteLine("\tmaclocker ");
138 | Console.WriteLine("\tmaclocker ");
139 | Console.WriteLine("\tmaclocker ");
140 | Console.WriteLine();
141 | Console.WriteLine("\tcomp:\tCN of the computer object");
142 | Console.WriteLine("\tkey:\tFileVault recovery key to store as BitLocker key");
143 | Console.WriteLine("\tOU DN:\tdistinguishedName of the OU containing the computer");
144 | Console.WriteLine("\tuser:\tsAMAccountName of the account to write the changes with");
145 | Console.WriteLine("\tpass:\tpassword of this account");
146 | Console.WriteLine();
147 | Console.WriteLine("Example:");
148 | Console.WriteLine();
149 | Console.WriteLine("maclocker mac01 UIER-IASD-U2DM-78DG-NM23-91DT OU=Mac,DC=xy,DC=lan admin1 P@ss");
150 | Console.WriteLine();
151 | Console.WriteLine("If OU DN or user/pass are omitted, the App.config values are used.");
152 | Console.WriteLine("If you set useOsAuth to true in App.config, user and pass are ignored.");
153 | }
154 |
155 | static void Main(string[] args)
156 | {
157 | String computerName;
158 | String recoveryKey;
159 | String adminUser;
160 | String adminPass;
161 | String ouPath;
162 | bool useOsAuth;
163 | ConsoleKeyInfo key;
164 |
165 | adminUser = ConfigurationManager.AppSettings["adminUser"];
166 | adminPass = ConfigurationManager.AppSettings["adminPass"];
167 | ouPath = ConfigurationManager.AppSettings["ouPath"];
168 |
169 | if (ConfigurationManager.AppSettings["useOsAuth"].Equals("true"))
170 | {
171 | useOsAuth = true;
172 | }
173 | else
174 | {
175 | useOsAuth = false;
176 | }
177 |
178 | switch (args.Length)
179 | {
180 | case 2:
181 | computerName = args[0];
182 | recoveryKey = args[1];
183 | break;
184 | case 3:
185 | computerName = args[0];
186 | recoveryKey = args[1];
187 | ouPath = args[2];
188 | break;
189 | case 5:
190 | computerName = args[0];
191 | recoveryKey = args[1];
192 | ouPath = args[2];
193 | adminUser = args[3];
194 | adminPass = args[4];
195 | break;
196 | default:
197 | PrintHelp();
198 | return;
199 | }
200 |
201 | Console.WriteLine("DN of the computer object:\tCN=" + computerName + "," + ouPath);
202 | Console.WriteLine("FileVault recovery password:\t" + recoveryKey);
203 | Console.WriteLine("Using OS authentication:\t" + useOsAuth.ToString());
204 | Console.Write("Store this key under this object? [y/n]\t");
205 | key = Console.ReadKey();
206 | Console.WriteLine();
207 |
208 | if (!key.Key.Equals(ConsoleKey.Y))
209 | {
210 | FinishUp();
211 | return;
212 | }
213 |
214 | WriteDashes();
215 |
216 | Console.Write("Checking for computer object: \t\t");
217 |
218 | if (ComputerExists(ouPath, computerName))
219 | {
220 | Console.WriteLine("exists");
221 | }
222 | else
223 | {
224 | Console.WriteLine("does not exist");
225 | Console.Write("Create computer object? [y/n]\t\t");
226 |
227 | key = Console.ReadKey();
228 | Console.WriteLine();
229 |
230 | if (key.Key.Equals(ConsoleKey.Y))
231 | {
232 | Console.Write("Creating computer object:\t\t");
233 |
234 | if (!CreateComputer(ouPath, computerName, useOsAuth, adminUser, adminPass))
235 | {
236 | Console.WriteLine("failure");
237 | FinishUp();
238 | return;
239 | }
240 | else
241 | {
242 | Console.WriteLine("success");
243 | }
244 | }
245 | else
246 | {
247 | FinishUp();
248 | return;
249 | }
250 | }
251 |
252 | Console.Write("Adding recovery key:\t\t\t");
253 |
254 | if (AddRecoveryKey(ouPath, computerName, recoveryKey, useOsAuth, adminUser, adminPass))
255 | {
256 | Console.WriteLine("success");
257 | }
258 | else
259 | {
260 | Console.WriteLine("failure");
261 | FinishUp();
262 | return;
263 | }
264 |
265 | FinishUp();
266 | }
267 | }
268 | }
269 |
--------------------------------------------------------------------------------
/maclocker/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("maclocker")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("maclocker")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("ed42de6c-1dfb-4fc2-814f-2769c468ed82")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/maclocker/maclocker.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {5871F3FB-F2CD-44E5-B449-03B31448BA70}
8 | Exe
9 | Properties
10 | maclocker
11 | maclocker
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
60 |
--------------------------------------------------------------------------------