Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 37 additions & 12 deletions lib/secretsscanner/authorizedkeys/users_list_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,54 @@
package authorizedkeys

/*
#cgo CFLAGS: -D_POSIX_PTHREAD_SEMANTICS
#include <pwd.h>
*/
import "C"

import (
"os/user"
"runtime"
"strconv"

"github.com/gravitational/trace"
)

// getHostUsers returns a list of all users on the host
// from local /etc/passwd file, LDAP, or other user databases.
func getHostUsers() (results []user.User, _ error) {
// getHostUsers returns the list of all users on the host from the user
// directory (depending on system configuration this can be /etc/passwd,
// LDAP...).
func getHostUsers() ([]user.User, error) {
// on darwin the setpwent/getpwent/endpwent functions use thread-local
// storage so there's no need for a global lock but we must call the whole
// sequence from the same thread
runtime.LockOSThread()
defer runtime.UnlockOSThread()

C.setpwent()
var result *C.struct_passwd
defer C.endpwent()

var results []user.User
for {
result = C.getpwent() /* on darwin, getpwent() is reentrant */
if result == nil {
break
result, err := C.getpwent()
// cgo error convention, check the return value before errno
Comment thread
codingllama marked this conversation as resolved.
if result != nil {
results = append(results, passwdC2Go(result))
continue
}
if err != nil {
return nil, trace.Wrap(err)
}
results = append(results, passwdC2Go(result))
return results, nil
}
}

C.endpwent()

return results, nil
// passwdC2Go converts `passwd` struct from C to golang native struct
func passwdC2Go(passwdC *C.struct_passwd) user.User {
name := C.GoString(passwdC.pw_name)
return user.User{
Name: name,
Username: name,
Uid: strconv.FormatUint(uint64(passwdC.pw_uid), 10),
Gid: strconv.FormatUint(uint64(passwdC.pw_gid), 10),
HomeDir: C.GoString(passwdC.pw_dir),
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//go:build !windows

/*
* Teleport
* Copyright (C) 2024 Gravitational, Inc.
Expand All @@ -21,21 +19,54 @@
package authorizedkeys

/*
#cgo CFLAGS: -D_POSIX_PTHREAD_SEMANTICS
#define _XOPEN_SOURCE 500
#include <pwd.h>
*/
import "C"

import (
"os/user"
"strconv"
"sync"

"github.com/gravitational/trace"
)

// pwentLock should be acquired when using MT-Unsafe race:pwent functions (i.e.
// setpwent/getpwent/endpwent).
var pwentLock sync.Mutex

// getHostUsers returns the list of all users on the host from the user
// directory (depending on system configuration this can be /etc/passwd,
// LDAP...).
func getHostUsers() ([]user.User, error) {
pwentLock.Lock()
defer pwentLock.Unlock()

C.setpwent()
defer C.endpwent()

var results []user.User
for {
result, err := C.getpwent()
// cgo error convention, check the return value before errno
if result != nil {
results = append(results, passwdC2Go(result))
continue
}
if err != nil {
return nil, trace.Wrap(err)
}
return results, nil
}
}

Comment thread
codingllama marked this conversation as resolved.
// passwdC2Go converts `passwd` struct from C to golang native struct
func passwdC2Go(passwdC *C.struct_passwd) user.User {
name := C.GoString(passwdC.pw_name)
return user.User{
Name: C.GoString(passwdC.pw_name),
Username: C.GoString(passwdC.pw_name),
Name: name,
Username: name,
Uid: strconv.FormatUint(uint64(passwdC.pw_uid), 10),
Gid: strconv.FormatUint(uint64(passwdC.pw_gid), 10),
HomeDir: C.GoString(passwdC.pw_dir),
Expand Down
38 changes: 38 additions & 0 deletions lib/secretsscanner/authorizedkeys/users_list_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Teleport
// Copyright (C) 2025 Gravitational, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

//go:build !darwin && !linux

package authorizedkeys

import (
"os/user"

"github.com/gravitational/trace"
)

var alwaysFalse bool

// getHostUsers returns ErrUnsupportedPlatform because this platform is not
// supported. On supported platforms, it returns the list of all users on the
// host from the user directory.
func getHostUsers() ([]user.User, error) {
if alwaysFalse {
// thwart the well-meaning intentions of staticcheck
Comment thread
codingllama marked this conversation as resolved.
return nil, nil
}
return nil, trace.Wrap(ErrUnsupportedPlatform)
}
67 changes: 0 additions & 67 deletions lib/secretsscanner/authorizedkeys/users_list_unix.go

This file was deleted.

Loading