Implement updating a client Pub+PSK when editing a client (#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.
This commit is contained in:
		
							parent
							
								
									7488f283c4
								
							
						
					
					
						commit
						364a43e3dc
					
				|  | @ -567,6 +567,45 @@ func UpdateClient(db store.IStore) echo.HandlerFunc { | ||||||
| 			return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, "Extra Allowed IPs must be in CIDR format"}) | 			return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, "Extra Allowed IPs must be in CIDR format"}) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		// update Wireguard Client PublicKey
 | ||||||
|  | 		if client.PublicKey != _client.PublicKey && _client.PublicKey != "" { | ||||||
|  | 			_, err := wgtypes.ParseKey(_client.PublicKey) | ||||||
|  | 			if err != nil { | ||||||
|  | 				log.Error("Cannot verify provided Wireguard public key: ", err) | ||||||
|  | 				return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot verify provided Wireguard public key"}) | ||||||
|  | 			} | ||||||
|  | 			// check for duplicates
 | ||||||
|  | 			clients, err := db.GetClients(false) | ||||||
|  | 			if err != nil { | ||||||
|  | 				log.Error("Cannot get client list for duplicate public key check") | ||||||
|  | 				return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot get client list for duplicate public key check"}) | ||||||
|  | 			} | ||||||
|  | 			for _, other := range clients { | ||||||
|  | 				if other.Client.PublicKey == _client.PublicKey { | ||||||
|  | 					log.Error("Duplicate Public Key") | ||||||
|  | 					return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Duplicate Public Key"}) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// When replacing any PublicKey, discard any locally stored Wireguard Client PrivateKey
 | ||||||
|  | 			// Client PubKey no longer corresponds to locally stored PrivKey.
 | ||||||
|  | 			// QR code (needs PrivateKey) for this client is no longer possible now.
 | ||||||
|  | 
 | ||||||
|  | 			if client.PrivateKey != "" { | ||||||
|  | 				client.PrivateKey = "" | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// update Wireguard Client PresharedKey
 | ||||||
|  | 		if client.PresharedKey != _client.PresharedKey && _client.PresharedKey != "" { | ||||||
|  | 			_, err := wgtypes.ParseKey(_client.PresharedKey) | ||||||
|  | 			if err != nil { | ||||||
|  | 				log.Error("Cannot verify provided Wireguard preshared key: ", err) | ||||||
|  | 				return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot verify provided Wireguard preshared key"}) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		// map new data
 | 		// map new data
 | ||||||
| 		client.Name = _client.Name | 		client.Name = _client.Name | ||||||
| 		client.Email = _client.Email | 		client.Email = _client.Email | ||||||
|  | @ -575,6 +614,8 @@ func UpdateClient(db store.IStore) echo.HandlerFunc { | ||||||
| 		client.AllocatedIPs = _client.AllocatedIPs | 		client.AllocatedIPs = _client.AllocatedIPs | ||||||
| 		client.AllowedIPs = _client.AllowedIPs | 		client.AllowedIPs = _client.AllowedIPs | ||||||
| 		client.ExtraAllowedIPs = _client.ExtraAllowedIPs | 		client.ExtraAllowedIPs = _client.ExtraAllowedIPs | ||||||
|  | 		client.PublicKey = _client.PublicKey | ||||||
|  | 		client.PresharedKey = _client.PresharedKey | ||||||
| 		client.UpdatedAt = time.Now().UTC() | 		client.UpdatedAt = time.Now().UTC() | ||||||
| 
 | 
 | ||||||
| 		// write to the database
 | 		// write to the database
 | ||||||
|  |  | ||||||
|  | @ -129,6 +129,26 @@ Wireguard Clients | ||||||
|                             </label> |                             </label> | ||||||
|                         </div> |                         </div> | ||||||
|                     </div> |                     </div> | ||||||
|  |                     <details> | ||||||
|  |                         <summary><strong>Public and Preshared Keys</strong> | ||||||
|  |                             <i class="fas fa-info-circle" data-toggle="tooltip" | ||||||
|  |                                data-original-title="Update the server stored | ||||||
|  |                                client Public and Preshared keys."> | ||||||
|  |                             </i> | ||||||
|  |                         </summary> | ||||||
|  |                         <div class="form-group" style="margin-top: 1rem"> | ||||||
|  |                             <label for="_client_public_key" class="control-label"> | ||||||
|  |                                 Public Key | ||||||
|  |                             </label> | ||||||
|  |                             <input type="text" class="form-control" id="_client_public_key" name="_client_public_key" aria-invalid="false"> | ||||||
|  |                         </div> | ||||||
|  |                         <div class="form-group"> | ||||||
|  |                             <label for="_client_preshared_key" class="control-label"> | ||||||
|  |                                 Preshared Key | ||||||
|  |                             </label> | ||||||
|  |                             <input type="text" class="form-control" id="_client_preshared_key" name="_client_preshared_key"> | ||||||
|  |                         </div> | ||||||
|  |                     </details> | ||||||
|                 </div> |                 </div> | ||||||
|                 <div class="modal-footer justify-content-between"> |                 <div class="modal-footer justify-content-between"> | ||||||
|                     <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> |                     <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> | ||||||
|  | @ -388,6 +408,7 @@ Wireguard Clients | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|         // Edit client modal event |         // Edit client modal event | ||||||
|  |         // This fills the modal dialogue with data from the DB when we open the edit menu | ||||||
|         $(document).ready(function () { |         $(document).ready(function () { | ||||||
|             $("#modal_edit_client").on('show.bs.modal', function (event) { |             $("#modal_edit_client").on('show.bs.modal', function (event) { | ||||||
|                 let modal = $(this); |                 let modal = $(this); | ||||||
|  | @ -458,6 +479,9 @@ Wireguard Clients | ||||||
| 
 | 
 | ||||||
|                         modal.find("#_use_server_dns").prop("checked", client.use_server_dns); |                         modal.find("#_use_server_dns").prop("checked", client.use_server_dns); | ||||||
|                         modal.find("#_enabled").prop("checked", client.enabled); |                         modal.find("#_enabled").prop("checked", client.enabled); | ||||||
|  | 
 | ||||||
|  |                         modal.find("#_client_public_key").val(client.public_key); | ||||||
|  |                         modal.find("#_client_preshared_key").val(client.preshared_key); | ||||||
|                     }, |                     }, | ||||||
|                     error: function (jqXHR, exception) { |                     error: function (jqXHR, exception) { | ||||||
|                         const responseJson = jQuery.parseJSON(jqXHR.responseText); |                         const responseJson = jQuery.parseJSON(jqXHR.responseText); | ||||||
|  | @ -523,6 +547,8 @@ Wireguard Clients | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // submitEditClient function for updating an existing client |         // submitEditClient function for updating an existing client | ||||||
|  |         // This sends dialogue data to the back-end when user presses "Save" | ||||||
|  |         // See e.g. routes.go:UpdateClient for where data is processed/verified. | ||||||
|         function submitEditClient() { |         function submitEditClient() { | ||||||
|             const client_id = $("#_client_id").val(); |             const client_id = $("#_client_id").val(); | ||||||
|             const name = $("#_client_name").val(); |             const name = $("#_client_name").val(); | ||||||
|  | @ -531,6 +557,8 @@ Wireguard Clients | ||||||
|             const allowed_ips = $("#_client_allowed_ips").val().split(","); |             const allowed_ips = $("#_client_allowed_ips").val().split(","); | ||||||
|             let use_server_dns = false; |             let use_server_dns = false; | ||||||
|             let extra_allowed_ips = []; |             let extra_allowed_ips = []; | ||||||
|  |             const public_key = $("#_client_public_key").val(); | ||||||
|  |             const preshared_key = $("#_client_preshared_key").val(); | ||||||
| 
 | 
 | ||||||
|             if( $("#_client_extra_allowed_ips").val() !== "" ) { |             if( $("#_client_extra_allowed_ips").val() !== "" ) { | ||||||
|                 extra_allowed_ips = $("#_client_extra_allowed_ips").val().split(","); |                 extra_allowed_ips = $("#_client_extra_allowed_ips").val().split(","); | ||||||
|  | @ -547,7 +575,7 @@ Wireguard Clients | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             const data = {"id": client_id, "name": name, "email": email, "allocated_ips": allocated_ips, |             const data = {"id": client_id, "name": name, "email": email, "allocated_ips": allocated_ips, | ||||||
|                 "allowed_ips": allowed_ips, "extra_allowed_ips": extra_allowed_ips, "use_server_dns": use_server_dns, "enabled": enabled}; |                 "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}; | ||||||
| 
 | 
 | ||||||
|             $.ajax({ |             $.ajax({ | ||||||
|                 cache: false, |                 cache: false, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue