2020-06-18 23:51:50 +02:00
// +build !windows,!linux
2018-06-13 16:52:41 +02:00
package main
import (
"os"
"os/exec"
"os/user"
"path/filepath"
2018-10-03 16:05:07 +02:00
"runtime"
2018-06-13 16:52:41 +02:00
"strconv"
2019-09-07 12:06:32 +02:00
"golang.org/x/sys/unix"
2018-06-13 17:24:16 +02:00
2018-06-13 16:52:41 +02:00
"github.com/jedisct1/dlog"
)
func ( proxy * Proxy ) dropPrivilege ( userStr string , fds [ ] * os . File ) {
2018-08-04 00:57:52 +02:00
currentUser , err := user . Current ( )
2018-10-08 17:48:05 +02:00
if err != nil && currentUser . Uid != "0" {
dlog . Fatal ( "Root privileges are required in order to switch to a different user. Maybe try again with 'sudo'" )
2018-08-04 00:57:52 +02:00
}
2019-09-07 12:06:32 +02:00
userInfo , err := user . Lookup ( userStr )
2018-06-13 16:52:41 +02:00
args := os . Args
if err != nil {
2019-09-07 12:06:32 +02:00
uid , err2 := strconv . Atoi ( userStr )
if err2 != nil || uid <= 0 {
dlog . Fatalf ( "Unable to retrieve any information about user [%s]: [%s] - Remove the user_name directive from the configuration file in order to avoid identity switch" , userStr , err )
}
dlog . Warnf ( "Unable to retrieve any information about user [%s]: [%s] - Switching to user id [%v] with the same group id, as [%v] looks like a user id. But you should remove or fix the user_name directive in the configuration file if possible" , userStr , err , uid , uid )
userInfo = & user . User { Uid : userStr , Gid : userStr }
2018-06-13 16:52:41 +02:00
}
2019-09-07 12:06:32 +02:00
uid , err := strconv . Atoi ( userInfo . Uid )
2018-06-13 16:52:41 +02:00
if err != nil {
dlog . Fatal ( err )
}
2019-09-07 12:06:32 +02:00
gid , err := strconv . Atoi ( userInfo . Gid )
2018-06-13 16:52:41 +02:00
if err != nil {
dlog . Fatal ( err )
}
2018-06-13 17:24:16 +02:00
execPath , err := exec . LookPath ( args [ 0 ] )
2018-06-13 16:52:41 +02:00
if err != nil {
2019-09-07 12:06:32 +02:00
dlog . Fatalf ( "Unable to get the path to the dnscrypt-proxy executable file: [%s]" , err )
2018-06-13 16:52:41 +02:00
}
2018-06-13 17:24:16 +02:00
path , err := filepath . Abs ( execPath )
2018-06-13 16:52:41 +02:00
if err != nil {
dlog . Fatal ( err )
}
2019-10-03 14:39:09 +02:00
if err := ServiceManagerReadyNotify ( ) ; err != nil {
dlog . Fatal ( err )
}
2018-07-07 17:21:21 +02:00
2018-06-13 17:24:16 +02:00
args = append ( args , "-child" )
2018-06-13 16:52:41 +02:00
dlog . Notice ( "Dropping privileges" )
2019-09-07 12:06:32 +02:00
2018-10-03 16:05:07 +02:00
runtime . LockOSThread ( )
2019-09-07 12:06:32 +02:00
if err := unix . Setgroups ( [ ] int { } ) ; err != nil {
dlog . Fatalf ( "Unable to drop additional groups: %s" , err )
2018-10-03 16:05:07 +02:00
}
2019-09-07 12:06:32 +02:00
if err := unix . Setgid ( gid ) ; err != nil {
2019-09-07 16:45:11 +02:00
dlog . Fatalf ( "Unable to drop group privileges: %s" , err )
2018-10-03 16:05:07 +02:00
}
2019-09-07 12:06:32 +02:00
if err := unix . Setuid ( uid ) ; err != nil {
dlog . Fatalf ( "Unable to drop user privileges: %s" , err )
2018-10-03 16:05:07 +02:00
}
for i , fd := range fds {
2020-06-18 23:51:50 +02:00
if fd . Fd ( ) >= InheritedDescriptorsBase {
dlog . Fatal ( "Duplicated file descriptors are above base" )
}
2020-06-19 21:42:20 +02:00
if err := unix . Dup2 ( int ( fd . Fd ( ) ) , int ( InheritedDescriptorsBase + uintptr ( i ) ) ) ; err != nil {
2019-09-07 12:06:32 +02:00
dlog . Fatalf ( "Unable to clone file descriptor: [%s]" , err )
2018-10-03 16:05:07 +02:00
}
2019-09-07 12:06:32 +02:00
if _ , err := unix . FcntlInt ( fd . Fd ( ) , unix . F_SETFD , unix . FD_CLOEXEC ) ; err != nil {
dlog . Fatalf ( "Unable to set the close on exec flag: [%s]" , err )
2018-10-03 16:05:07 +02:00
}
}
2019-09-07 12:06:32 +02:00
err = unix . Exec ( path , args , os . Environ ( ) )
2018-10-05 01:06:44 +02:00
dlog . Fatalf ( "Unable to reexecute [%s]: [%s]" , path , err )
2018-10-03 16:05:07 +02:00
os . Exit ( 1 )
2018-06-13 16:52:41 +02:00
}