Skip to content

Commit 364a43e

Browse files
authored
Implement updating a client Pub+PSK when editing a client (ngoduykhanh#401)
This covers the normal use-case where clients generate keys locally on their device and notify the server of their new/updated keys. The server verifies Preshared and Public keys independently of each other. Should a client generate a new tunnel which lacks a PSK and send only a Public key to the server (admin) where the earlier server created profile has a Preshared key, the server admin/user must determine the course of action: keep or remove the PSK.
1 parent 7488f28 commit 364a43e

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-1
lines changed

handler/routes.go

+41
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,45 @@ func UpdateClient(db store.IStore) echo.HandlerFunc {
567567
return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, "Extra Allowed IPs must be in CIDR format"})
568568
}
569569

570+
// update Wireguard Client PublicKey
571+
if client.PublicKey != _client.PublicKey && _client.PublicKey != "" {
572+
_, err := wgtypes.ParseKey(_client.PublicKey)
573+
if err != nil {
574+
log.Error("Cannot verify provided Wireguard public key: ", err)
575+
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot verify provided Wireguard public key"})
576+
}
577+
// check for duplicates
578+
clients, err := db.GetClients(false)
579+
if err != nil {
580+
log.Error("Cannot get client list for duplicate public key check")
581+
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot get client list for duplicate public key check"})
582+
}
583+
for _, other := range clients {
584+
if other.Client.PublicKey == _client.PublicKey {
585+
log.Error("Duplicate Public Key")
586+
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Duplicate Public Key"})
587+
}
588+
}
589+
590+
// When replacing any PublicKey, discard any locally stored Wireguard Client PrivateKey
591+
// Client PubKey no longer corresponds to locally stored PrivKey.
592+
// QR code (needs PrivateKey) for this client is no longer possible now.
593+
594+
if client.PrivateKey != "" {
595+
client.PrivateKey = ""
596+
}
597+
598+
}
599+
600+
// update Wireguard Client PresharedKey
601+
if client.PresharedKey != _client.PresharedKey && _client.PresharedKey != "" {
602+
_, err := wgtypes.ParseKey(_client.PresharedKey)
603+
if err != nil {
604+
log.Error("Cannot verify provided Wireguard preshared key: ", err)
605+
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot verify provided Wireguard preshared key"})
606+
}
607+
}
608+
570609
// map new data
571610
client.Name = _client.Name
572611
client.Email = _client.Email
@@ -575,6 +614,8 @@ func UpdateClient(db store.IStore) echo.HandlerFunc {
575614
client.AllocatedIPs = _client.AllocatedIPs
576615
client.AllowedIPs = _client.AllowedIPs
577616
client.ExtraAllowedIPs = _client.ExtraAllowedIPs
617+
client.PublicKey = _client.PublicKey
618+
client.PresharedKey = _client.PresharedKey
578619
client.UpdatedAt = time.Now().UTC()
579620

580621
// write to the database

templates/clients.html

+29-1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,26 @@ <h4 class="modal-title">Edit Client</h4>
129129
</label>
130130
</div>
131131
</div>
132+
<details>
133+
<summary><strong>Public and Preshared Keys</strong>
134+
<i class="fas fa-info-circle" data-toggle="tooltip"
135+
data-original-title="Update the server stored
136+
client Public and Preshared keys.">
137+
</i>
138+
</summary>
139+
<div class="form-group" style="margin-top: 1rem">
140+
<label for="_client_public_key" class="control-label">
141+
Public Key
142+
</label>
143+
<input type="text" class="form-control" id="_client_public_key" name="_client_public_key" aria-invalid="false">
144+
</div>
145+
<div class="form-group">
146+
<label for="_client_preshared_key" class="control-label">
147+
Preshared Key
148+
</label>
149+
<input type="text" class="form-control" id="_client_preshared_key" name="_client_preshared_key">
150+
</div>
151+
</details>
132152
</div>
133153
<div class="modal-footer justify-content-between">
134154
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
@@ -388,6 +408,7 @@ <h4 class="modal-title">Remove</h4>
388408

389409

390410
// Edit client modal event
411+
// This fills the modal dialogue with data from the DB when we open the edit menu
391412
$(document).ready(function () {
392413
$("#modal_edit_client").on('show.bs.modal', function (event) {
393414
let modal = $(this);
@@ -458,6 +479,9 @@ <h4 class="modal-title">Remove</h4>
458479

459480
modal.find("#_use_server_dns").prop("checked", client.use_server_dns);
460481
modal.find("#_enabled").prop("checked", client.enabled);
482+
483+
modal.find("#_client_public_key").val(client.public_key);
484+
modal.find("#_client_preshared_key").val(client.preshared_key);
461485
},
462486
error: function (jqXHR, exception) {
463487
const responseJson = jQuery.parseJSON(jqXHR.responseText);
@@ -523,6 +547,8 @@ <h4 class="modal-title">Remove</h4>
523547
}
524548

525549
// submitEditClient function for updating an existing client
550+
// This sends dialogue data to the back-end when user presses "Save"
551+
// See e.g. routes.go:UpdateClient for where data is processed/verified.
526552
function submitEditClient() {
527553
const client_id = $("#_client_id").val();
528554
const name = $("#_client_name").val();
@@ -531,6 +557,8 @@ <h4 class="modal-title">Remove</h4>
531557
const allowed_ips = $("#_client_allowed_ips").val().split(",");
532558
let use_server_dns = false;
533559
let extra_allowed_ips = [];
560+
const public_key = $("#_client_public_key").val();
561+
const preshared_key = $("#_client_preshared_key").val();
534562

535563
if( $("#_client_extra_allowed_ips").val() !== "" ) {
536564
extra_allowed_ips = $("#_client_extra_allowed_ips").val().split(",");
@@ -547,7 +575,7 @@ <h4 class="modal-title">Remove</h4>
547575
}
548576

549577
const data = {"id": client_id, "name": name, "email": email, "allocated_ips": allocated_ips,
550-
"allowed_ips": allowed_ips, "extra_allowed_ips": extra_allowed_ips, "use_server_dns": use_server_dns, "enabled": enabled};
578+
"allowed_ips": allowed_ips, "extra_allowed_ips": extra_allowed_ips, "use_server_dns": use_server_dns, "enabled": enabled, "public_key": public_key, "preshared_key": preshared_key};
551579

552580
$.ajax({
553581
cache: false,

0 commit comments

Comments
 (0)