go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/users/etcpasswd.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package users
     5  
     6  import (
     7  	"bufio"
     8  	"io"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/rs/zerolog/log"
    13  	"go.mondoo.com/cnquery/providers/os/connection/shared"
    14  )
    15  
    16  // a good description of this file is available at:
    17  // https://www.cyberciti.biz/faq/understanding-etcpasswd-file-format/
    18  func ParseEtcPasswd(input io.Reader) ([]*User, error) {
    19  	var users []*User
    20  	scanner := bufio.NewScanner(input)
    21  	for scanner.Scan() {
    22  		line := scanner.Text()
    23  
    24  		// check if line starts with #
    25  		if strings.HasPrefix(strings.TrimSpace(line), "#") {
    26  			continue
    27  		}
    28  
    29  		m := strings.Split(line, ":")
    30  
    31  		if len(m) >= 7 {
    32  			// parse uid
    33  			uid, err := strconv.ParseInt(m[2], 10, 0)
    34  			if err != nil {
    35  				log.Error().Err(err).Str("user", m[0]).Msg("could not parse uid")
    36  			}
    37  			gid, err := strconv.ParseInt(m[3], 10, 0)
    38  			if err != nil {
    39  				log.Error().Err(err).Str("user", m[0]).Msg("could not parse gid")
    40  			}
    41  
    42  			// bin:x:1:1:bin:/bin:/sbin/nologin
    43  			users = append(users, &User{
    44  				ID:          m[2],
    45  				Name:        m[0],
    46  				Uid:         uid,
    47  				Gid:         gid,
    48  				Description: m[4],
    49  				Home:        m[5],
    50  				Shell:       m[6],
    51  			})
    52  		}
    53  	}
    54  
    55  	return users, nil
    56  }
    57  
    58  type UnixUserManager struct {
    59  	conn shared.Connection
    60  }
    61  
    62  func (s *UnixUserManager) Name() string {
    63  	return "Unix User Manager"
    64  }
    65  
    66  func (s *UnixUserManager) User(id string) (*User, error) {
    67  	users, err := s.List()
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	return findUser(users, id)
    73  }
    74  
    75  func (s *UnixUserManager) List() ([]*User, error) {
    76  	f, err := s.conn.FileSystem().Open("/etc/passwd")
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	defer f.Close()
    81  	return ParseEtcPasswd(f)
    82  }