Skip to content

Commit

Permalink
Merge pull request #11 from thrasr/master
Browse files Browse the repository at this point in the history
Big fix, external js files, and other minor updates.
  • Loading branch information
thrasr committed Aug 4, 2014
2 parents 49efc26 + 445f865 commit a185e4f
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 221 deletions.
18 changes: 18 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Python related files
server/*.pyc

# Logs/storage with possible sensitive information
server/xactn.log
server/devicelist.pickle

# Certs with sensitive information
server/CA.crt
server/Enroll.mobileconfig
server/Identity.p12
server/PushCert.pem
server/Server.*
server/identity.crt

# Custom payloads
server/Manifest.plist
server/MyApp.*
22 changes: 10 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,13 @@ Instructions and code for setting up a simple iOS Mobile Device Management (MDM)
2. Go to Apple's [iOS Provisioning Portal](Apple Member Center). Upload **customer.csr** in the **/scripts** folder on the iOS Provisioning Portal.
* You will be given the option to download a .cer file. Do so and name this file something along the lines of YOUR_MDM.cer.
* Run the following openssl command in your terminal and then move the generated mdm.pem file to **/vendor-signing/com/softhinker** (it should replace an empty file of the same name).

openssl x509 -inform der -in YOUR_MDM.cer -out mdm.pem

* <code>openssl x509 -inform der -in YOUR_MDM.cer -out mdm.pem</code>
3. Find **Test.java** in the **/vendor-signing/com/softhinker** folder. On line 95, replace the word *test* with the PEM password that you used when running make_certs.sh.
* Replace only the word test so that your password is still in quotes.
4. Run the **vendor-signing.sh** script found in the **/scripts** directory.
* There now should be a file named plist_encoded located in **/vendor-signing**.
5. Go to [Apple's Push Certificates Portal](https://identity.apple.com/pushcert/) and upload the plist_encoded file. Download the certificate as **PushCert.pem** and place it within the **/server** directory.
* Notice the (i) icon beside the renew option. If you click it there will be a long string of text ending in **UID=com.apple.mgmt...**, make sure to copy that string starting at **com** since you will need it later.
* Notice the (i) icon beside the renew option. If you click it there will be a long string of text ending in **UID=com.apple.mgmt...**, make sure to copy that string starting at **com** since you will need it later on in the enrollment process.

![Apple Portal](images/certPortal.png)

Expand Down Expand Up @@ -67,17 +65,17 @@ After generating certificates and placing your PEM password in line 95 of Test.j

# Enrollment profile

Open the **iPhone Configuration Utilities** program. Select **Configuration Profiles** click the **New** button, and fill out the sections as follows:
Open the **iPhone Configuration Utilities** program. Select **Configuration Profiles**, click the **New** button, and fill out the sections as follows:
* General
* Name: A unique name for you to keep track of
* Identifier: **com.apple.mgmt...** string you recorded during certificate generation
* Identifier: **com.apple.mgmt...** string you recorded during certificate generation (see step 5 of the certificate setup instructions)
* Certificates
* Use **vendor.p12** generated during certificate creation
* Password: Enter the password you used during certificate creation
* Use **vendor.p12** generated during certificate creation (should be in the /vendor-signing/com/softhinker/ directory)
* Password: Enter the PEM password you used during certificate creation
* Mobile Device Management
* Server URL: https://YOUR_HOSTNAME:8080/server
* Check In URL: https://YOUR_HOSTNAME:8080/checkin
* Topic: **com.apple.mgmt...** string
* Topic: **com.apple.mgmt...** string (same as General->Identifier)
* Identity: vendor.p12
* Sign messages: Checked
* Check out when removed: Unchecked
Expand All @@ -99,7 +97,7 @@ Finally, some versions of IPCU don't include the correct settings for all versio

# Server Setup

The server code based on and heavily takes from [Intrepidus Group's blackhat presentation](https://intrepidusgroup.com/). Copy over the **mdm-server/server** directory you put the enrollment profile and certificates in to your server.
The server code is based on and heavily takes from [Intrepidus Group's blackhat presentation](https://intrepidusgroup.com/). Copy over the **mdm-server/server** directory you put the enrollment profile and certificates in to your server.

You must have the following installed on the server:
* Openssl
Expand All @@ -123,7 +121,7 @@ Once there you need to, in order:
1. Tap *here* to install the CA Cert (for Server/Identity)
2. Tap *here* to enroll in MDM (the device should appear after this step)
3. Select Command (DeviceLock is a good one to test) and check your device. Click Submit to send the command.
4. If everything works, you're good to go! As of right now some of the commands aren't fully implemented. Feel free to experiment with different commands!
4. If everything works, the device should lock and you're good to go! As of right now some of the commands aren't fully implemented. Feel free to experiment with different commands!

---
![Device Enrollment Steps](images/deviceEnroll.jpg)
Expand All @@ -135,7 +133,7 @@ You can now run those commands from any web browser, a successfull command will
![Command Success](images/commandSuccess.png)
---

Click the "Response" button to see the plist response from apple.
Click the "Response" button to see the plist response from apple. Click the pencil to edit the device name, device owner, and device location.


# Client Reporting
Expand Down
4 changes: 2 additions & 2 deletions server/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ def __init__(self, newUDID, tuple):

# Hard coded information to show possible features
self.GEO = "42*21'29''N 71*03'49''W"

# Owner and location default to unassigned
self.owner = 'Unassigned'
self.location = 'Unassigned'


self.status = 0 # 0=ready for command (green? gray?)
# 1=command in queue (yellow)
# 2=error/timeout (red)
# maybe have green (last command successful?)


# Possible additional parameters based on query commands
#self.availableCapacity
#self.totalCapacity
Expand Down
6 changes: 5 additions & 1 deletion server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -466,8 +466,12 @@ def POST(self):
global device_list

i = json.loads(web.data())
try:
return device_list[i['UDID']].getResponse(i['UUID'])
except:
print "ERROR: Unable to lookup response by command UUID"
return "ERROR: Unable to retrieve response"

return device_list[i['UDID']].getResponse(i['UUID'])

class dev_tab:
def POST(self):
Expand Down
4 changes: 2 additions & 2 deletions server/static/devices.mustache.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ <h4 class="panel-title">
</thead>
<tbody>
{{#commands}}
<tr id="command{{cmd.CommandUUID}}">
<tr id="command{{response.CommandUUID}}">
<td><span class="glyphicon {{status}} glyphicon-certificate"></span></td>
<td>{{cmd.Command.RequestType}}</td>
<td><button type="button" class="btn btn-xs btn-primary response-btn" id="{{cmd.CommandUUID}}" data-toggle="modal" data-target="#modal">Response</button></td>
<td><button type="button" class="btn btn-xs btn-primary response-btn" id="{{response.CommandUUID}}" data-toggle="modal" data-target="#modal">Response</button></td>
</tr>
{{/commands}}
</tbody>
Expand Down
45 changes: 45 additions & 0 deletions server/static/dist/js/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
$(document).ready(function(){
// Initial setup
update_cmds()

// Start polling
populate_devices();
setInterval(populate_devices, 2000);

// Check for device-specific content and enable if applicable
if(checkDevice()){
document.getElementById("showEnroll").style.display="block";
document.getElementById("showCert").style.display="block";
}

// Submit button functionality
$("#submitcmd").click(function(event){
var checked_devices = [];

// Get all selected devices
$(".row_box").each(function(){
if(this.checked){
checked_devices.push($(this).closest(".panel").attr("id"));
}
});

// Input checking.
if ($("#commands").val()==0){
alert("Please choose a command.");
}
else if (checked_devices.length==0){
alert("Please choose one or more devices.");
}
else{
// Send AJAX request
// Variable to pass all necessary data to server
var parameters = {
"cmd":$("#commands").val(),
"dev[]":checked_devices
};

// Use stringify to fix odd error with passing just parameters
$.post("/queue", JSON.stringify(parameters), function(){});
}
});
});
60 changes: 60 additions & 0 deletions server/static/dist/js/populate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Global variable to avoid changing device list if there are no changes to it
var checksum = ''

function populate_devices(){
// Populates device accordion using data from server
$.post("/devices", function(raw){

// Check if any changes have been made
if(checksum == JSON.stringify(raw)){
return;
}
else{
checksum = JSON.stringify(raw);
}

// Use mustache to populate the accordion
$.get("devices.mustache.html", function(template){
var rendered = Mustache.render(template, jQuery.parseJSON(raw));
$('#accordion').html(rendered);

// Set response button on click to update the modal
$(".response-btn").click(function(event){
// Get device UDID and command UUID
var udid = $(this).closest(".panel").attr("id");
var uuid = $(this).attr("id");

// Access /response to get the response string
$.post("/response", JSON.stringify({"UDID":udid, "UUID":uuid}), function(data){
$("#modal_body").html(data);
});
});

// Puts HTML content inside the popover
$(".trigger").popover({
html: true,
title: function () {
return $(this).parent().find('.head').html();
},
content: function () {
return $(this).parent().find('.content').html();
}
});

// Submit input group when submit button clicked
$('body').on('click', '.popover-submit', function(){
// Get UDID and form values
var udid = $(this).attr("id");
var name = $(this).parent().find("#input-name").val();
var owner = $(this).parent().find("#owner-name").val();
var location = $(this).parent().find("#location-name").val();

// POST data to /metadata endpoint
$.post("/metadata", JSON.stringify({"UDID":udid,"name":name,"owner":owner,"location":location}), function(){});

$("#metadatapopover".concat(udid)).popover("hide");
});

});
});
}
21 changes: 21 additions & 0 deletions server/static/dist/js/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
function update_cmds(){
// Populate command list
$.post("/getcommands", function(cmd_list){
cmds = JSON.parse(cmd_list);
x = document.getElementById("commands");
x.options.length = 0
x.options[x.options.length] = new Option("Select Command", "", true, false);
for(i=0;i<cmds.length;i++){
x.options[x.options.length] = new Option(cmds[i][0], cmds[i][1]);
}
});
}

function checkDevice(){
// Returns true if site is accessed using an iDevice
var agent = navigator.userAgent;
if (agent.match(/(iPhone|iPod|iPad)/)){
return true;
}
return false;
}
Loading

0 comments on commit a185e4f

Please sign in to comment.