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

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package shadow
     5  
     6  import (
     7  	"encoding/csv"
     8  	"io"
     9  	"strconv"
    10  	"strings"
    11  	"time"
    12  )
    13  
    14  type ShadowEntry struct {
    15  	User         string
    16  	Password     string
    17  	LastChanged  *time.Time
    18  	MinDays      string
    19  	MaxDays      string
    20  	WarnDays     string
    21  	InactiveDays string
    22  	ExpiryDates  string
    23  	Reserved     string
    24  }
    25  
    26  func ParseShadow(r io.Reader) ([]ShadowEntry, error) {
    27  	res := []ShadowEntry{}
    28  
    29  	csvReader := csv.NewReader(r)
    30  	csvReader.Comma = ':'
    31  	for {
    32  		record, err := csvReader.Read()
    33  		if err == io.EOF {
    34  			break
    35  		}
    36  		if err != nil {
    37  			return nil, err
    38  		}
    39  		// the /etc/shadow file gives the count of days since jan 1, 1970
    40  		start := time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC)
    41  		var lastChangedTime *time.Time
    42  		if record[2] == "" {
    43  			// if the last_changes field is an empty string, nothing was ever changed, return nil
    44  			lastChangedTime = nil
    45  		} else {
    46  			i, err := strconv.Atoi(record[2])
    47  			if err != nil {
    48  				return nil, err
    49  			}
    50  			date := start.Add(time.Hour * 24 * time.Duration(i))
    51  			lastChangedTime = &date
    52  		}
    53  		res = append(res, ShadowEntry{
    54  			User:         strings.TrimSpace(record[0]),
    55  			Password:     strings.TrimSpace(record[1]),
    56  			LastChanged:  lastChangedTime,
    57  			MinDays:      strings.TrimSpace(record[3]),
    58  			MaxDays:      strings.TrimSpace(record[4]),
    59  			WarnDays:     strings.TrimSpace(record[5]),
    60  			InactiveDays: strings.TrimSpace(record[6]),
    61  			ExpiryDates:  strings.TrimSpace(record[7]),
    62  			Reserved:     strings.TrimSpace(record[8]),
    63  		})
    64  	}
    65  
    66  	return res, nil
    67  }