| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | package server | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"crypto/md5" | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2020-11-09 23:43:57 +01:00
										 |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"syscall" | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/h44z/wg-portal/internal/common" | 
					
						
							|  |  |  | 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | func (s *Server) PrepareNewUser() (Peer, error) { | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	device := s.users.GetDevice() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 	peer := Peer{} | 
					
						
							|  |  |  | 	peer.IsNew = true | 
					
						
							|  |  |  | 	peer.AllowedIPsStr = device.AllowedIPsStr | 
					
						
							|  |  |  | 	peer.IPs = make([]string, len(device.IPs)) | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	for i := range device.IPs { | 
					
						
							|  |  |  | 		freeIP, err := s.users.GetAvailableIp(device.IPs[i]) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 			return Peer{}, err | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 		peer.IPs[i] = freeIP | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 	peer.IPsStr = common.ListToString(peer.IPs) | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	psk, err := wgtypes.GenerateKey() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 		return Peer{}, err | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	key, err := wgtypes.GeneratePrivateKey() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 		return Peer{}, err | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 	peer.PresharedKey = psk.String() | 
					
						
							|  |  |  | 	peer.PrivateKey = key.String() | 
					
						
							|  |  |  | 	peer.PublicKey = key.PublicKey().String() | 
					
						
							|  |  |  | 	peer.UID = fmt.Sprintf("u%x", md5.Sum([]byte(peer.PublicKey))) | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 	return peer, nil | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *Server) CreateUserByEmail(email, identifierSuffix string, disabled bool) error { | 
					
						
							|  |  |  | 	ldapUser := s.ldapUsers.GetUserData(s.ldapUsers.GetUserDNByMail(email)) | 
					
						
							|  |  |  | 	if ldapUser.DN == "" { | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 		return errors.New("no peer with email " + email + " found") | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	device := s.users.GetDevice() | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 	peer := Peer{} | 
					
						
							|  |  |  | 	peer.AllowedIPsStr = device.AllowedIPsStr | 
					
						
							|  |  |  | 	peer.IPs = make([]string, len(device.IPs)) | 
					
						
							| 
									
										
										
										
											2020-11-09 23:24:14 +01:00
										 |  |  | 	for i := range device.IPs { | 
					
						
							|  |  |  | 		freeIP, err := s.users.GetAvailableIp(device.IPs[i]) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 		peer.IPs[i] = freeIP | 
					
						
							| 
									
										
										
										
											2020-11-09 23:24:14 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 	peer.IPsStr = common.ListToString(peer.IPs) | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	psk, err := wgtypes.GenerateKey() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	key, err := wgtypes.GeneratePrivateKey() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 	peer.PresharedKey = psk.String() | 
					
						
							|  |  |  | 	peer.PrivateKey = key.String() | 
					
						
							|  |  |  | 	peer.PublicKey = key.PublicKey().String() | 
					
						
							|  |  |  | 	peer.UID = fmt.Sprintf("u%x", md5.Sum([]byte(peer.PublicKey))) | 
					
						
							|  |  |  | 	peer.Email = email | 
					
						
							|  |  |  | 	peer.Identifier = fmt.Sprintf("%s %s (%s)", ldapUser.Firstname, ldapUser.Lastname, identifierSuffix) | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	now := time.Now() | 
					
						
							|  |  |  | 	if disabled { | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 		peer.DeactivatedAt = &now | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 	return s.CreateUser(peer) | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | func (s *Server) CreateUser(user Peer) error { | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	device := s.users.GetDevice() | 
					
						
							|  |  |  | 	user.AllowedIPsStr = device.AllowedIPsStr | 
					
						
							| 
									
										
										
										
											2020-11-09 23:24:14 +01:00
										 |  |  | 	if len(user.IPs) == 0 { | 
					
						
							|  |  |  | 		for i := range device.IPs { | 
					
						
							|  |  |  | 			freeIP, err := s.users.GetAvailableIp(device.IPs[i]) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			user.IPs[i] = freeIP | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		user.IPsStr = common.ListToString(user.IPs) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	if user.PrivateKey == "" { // if private key is empty create a new one | 
					
						
							|  |  |  | 		psk, err := wgtypes.GenerateKey() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		key, err := wgtypes.GeneratePrivateKey() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		user.PresharedKey = psk.String() | 
					
						
							|  |  |  | 		user.PrivateKey = key.String() | 
					
						
							|  |  |  | 		user.PublicKey = key.PublicKey().String() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	user.UID = fmt.Sprintf("u%x", md5.Sum([]byte(user.PublicKey))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 23:24:14 +01:00
										 |  |  | 	// Create WireGuard interface | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	if user.DeactivatedAt == nil { | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 		if err := s.wg.AddPeer(user.GetConfig()); err != nil { | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create in database | 
					
						
							|  |  |  | 	if err := s.users.CreateUser(user); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 23:43:57 +01:00
										 |  |  | 	return s.WriteWireGuardConfigFile() | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | func (s *Server) UpdateUser(user Peer, updateTime time.Time) error { | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	currentUser := s.users.GetUserByKey(user.PublicKey) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Update WireGuard device | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	switch { | 
					
						
							|  |  |  | 	case user.DeactivatedAt == &updateTime: | 
					
						
							|  |  |  | 		err = s.wg.RemovePeer(user.PublicKey) | 
					
						
							|  |  |  | 	case user.DeactivatedAt == nil && currentUser.Peer != nil: | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 		err = s.wg.UpdatePeer(user.GetConfig()) | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	case user.DeactivatedAt == nil && currentUser.Peer == nil: | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 		err = s.wg.AddPeer(user.GetConfig()) | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Update in database | 
					
						
							|  |  |  | 	if err := s.users.UpdateUser(user); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 23:43:57 +01:00
										 |  |  | 	return s.WriteWireGuardConfigFile() | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | func (s *Server) DeleteUser(user Peer) error { | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | 	// Delete WireGuard peer | 
					
						
							|  |  |  | 	if err := s.wg.RemovePeer(user.PublicKey); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Delete in database | 
					
						
							|  |  |  | 	if err := s.users.DeleteUser(user); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 23:43:57 +01:00
										 |  |  | 	return s.WriteWireGuardConfigFile() | 
					
						
							| 
									
										
										
										
											2020-11-09 11:06:02 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-11-09 23:36:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (s *Server) RestoreWireGuardInterface() error { | 
					
						
							|  |  |  | 	activeUsers := s.users.GetActiveUsers() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := range activeUsers { | 
					
						
							|  |  |  | 		if activeUsers[i].Peer == nil { | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 			if err := s.wg.AddPeer(activeUsers[i].GetConfig()); err != nil { | 
					
						
							| 
									
										
										
										
											2020-11-09 23:36:19 +01:00
										 |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-11-09 23:43:57 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (s *Server) WriteWireGuardConfigFile() error { | 
					
						
							|  |  |  | 	if s.config.WG.WireGuardConfig == "" { | 
					
						
							|  |  |  | 		return nil // writing disabled | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := syscall.Access(s.config.WG.WireGuardConfig, syscall.O_RDWR); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	device := s.users.GetDevice() | 
					
						
							| 
									
										
										
										
											2021-02-21 23:23:58 +01:00
										 |  |  | 	cfg, err := device.GetConfigFile(s.users.GetActiveUsers()) | 
					
						
							| 
									
										
										
										
											2020-11-09 23:43:57 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := ioutil.WriteFile(s.config.WG.WireGuardConfig, cfg, 0644); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |