Skip to content

Commit

Permalink
Adds 4 new user properties to the UserDetail check. (#146)
Browse files Browse the repository at this point in the history
* Adds 4 new user properties to the UserDetail check.

Signed-off-by: Mobmaker <[email protected]>

* Add modifier check type

Signed-off-by: Mobmaker <[email protected]>

* Updated documentation to match the "modifier" field

Signed-off-by: Mobmaker <[email protected]>

* Updated to ensure that users know time should be in UTC

Signed-off-by: Mobmaker <[email protected]>

* Removed debug lines

Signed-off-by: Mobmaker <[email protected]>

* Removed the modifier field and switched to a comparison value split system.

Signed-off-by: Mobmaker <[email protected]>

* Made comparison stricter, reducing edge cases.

Signed-off-by: Mobmaker <[email protected]>

* Handled more errors, optimized some code.

Signed-off-by: Mobmaker <[email protected]>

* Fixed error handling inversion

Signed-off-by: Mobmaker <[email protected]>

* fixed documentational wording

Signed-off-by: Mobmaker <[email protected]>

* Removed false positive

Signed-off-by: Mobmaker <[email protected]>
  • Loading branch information
Mobmaker55 authored Aug 7, 2022
1 parent b808a6e commit fe3f105
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.DEFAULT_GOAL := all
.SILENT: release-lin
.SILENT: release-lin release-win release

all:
CGO_ENABLED=0 GOOS=windows go build -ldflags '-s -w' -tags phocus -o ./phocus.exe . && \
Expand Down
72 changes: 68 additions & 4 deletions checks_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,14 +337,78 @@ func (c cond) UserDetail() (bool, error) {
c.requireArgs("User", "Key", "Value")
c.Value = strings.TrimSpace(c.Value)
c.Key = strings.TrimSpace(c.Key)
lookingFor := false
if strings.ToLower(c.Value) == "yes" {
lookingFor = true
}
splitVal := c.Value
lookingFor := strings.ToLower(c.Value) == "yes"
user, err := getLocalUser(c.User)
if err != nil {
return false, err
}
if c.Key == "PasswordAge" || c.Key == "BadPasswordCount" || c.Key == "NumberOfLogons" {
var num int
switch c.Key {
case "PasswordAge":
num = int(user.PasswordAge.Hours() / 24)
case "BadPasswordCount":
num = int(user.BadPasswordCount)
case "NumberOfLogons":
num = int(user.NumberOfLogons)
}
if len(c.Value) < 1 {
fail("Invalid value input:", c.Value)
return false, errors.New("invalid c.Value range")
}
var val int
switch c.Value[0] {
case '<':
splitVal = strings.Split(c.Value, "<")[1]
val, err = strconv.Atoi(splitVal)
if err == nil {
return num < val, nil
}
case '>':
splitVal = strings.Split(c.Value, ">")[1]
val, err = strconv.Atoi(splitVal)
if err == nil {
return num > val, nil
}
default:
val, err = strconv.Atoi(splitVal)
if err == nil {
return num == val, nil
}

}
fail("c.Value not an integer:", val)
return false, err
}

//Monday, January 02, 2006 3:04:05 PM
if c.Key == "LastLogon" {
lastLogon := user.LastLogon.UTC()
var timeComparison func(time.Time) bool
var timeString string
if len(c.Value) < 2 {
fail("Could not parse date: \"" + c.Value + "\". Correct format is \"Monday, January 02, 2006 3:04:05 PM\" and in UTC time.")
return false, errors.New("invalid c.Value date")
}
switch c.Value[0] {
case '<':
timeString = strings.Split(c.Value, "<")[1]
timeComparison = lastLogon.Before
case '>':
timeString = strings.Split(c.Value, ">")[1]
timeComparison = lastLogon.After
default:
timeComparison = lastLogon.Equal
}
parse, err := time.Parse("Monday, January 02, 2006 3:04:05 PM", timeString)
if err != nil {
fail("Could not parse date: \"" + c.Value + "\". Correct format is \"Monday, January 02, 2006 3:04:05 PM\" and in UTC time.")
return false, err
}
return timeComparison(parse), nil
}

switch c.Key {
case "FullName":
if user.FullName == c.Value {
Expand Down
9 changes: 9 additions & 0 deletions docs/checks.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,15 @@ value = 'No'

> See [here](userproperties.md) for all `UserDetail` properties.
> **Note!** For non-boolean details, you can use modifiers in the value field to specify the comparison.
> This is specified in the above property document.
```
type = 'UserDetail'
user = 'Administrator'
key = 'PasswordAge'
value = '>90'
```


**UserRights**: pass if specified user or group has specified privilege

Expand Down
30 changes: 27 additions & 3 deletions docs/userproperties.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

## Windows User Properties

These are the user properties that you would normally find the the user edit dialog.
These are the user properties that you would normally find the user edit dialog. (Plus some extra goodies!)

**Usernames are case sensitive.** `Yes`/`No` are not case sensitive. If you input something other than "yes" or "no" for a boolean check, it defaults to "no".
**Usernames are case-sensitive.** `Yes`/`No` are not case-sensitive. If you input something other than "yes" or "no" for a boolean check, it defaults to "no".

- `FullName`: Full name of user (case sensitive)
- `FullName`: Full name of user (case-sensitive)
- `IsEnabled`: Yes or No
- This returns for whether the account is **disabled**.
- `IsLocked`: Yes or No
Expand All @@ -18,3 +18,27 @@ These are the user properties that you would normally find the the user edit dia
- Password does not expire.
- `NoPasswordChange`: Yes or No
- Password cannot be changed.

For these checks, you can specify comparison through less, greater, and equal to through adding characters to the beginning of the value field.
This character **must** be added as the first character of the value field, as shown below.
>`<[value]`: The property is less than the `value` field.
>
>`>[value]`: The property is greater than the `value` field.
>
>`[value]`: The property is equal to the `value` field. This is the default.
- `PasswordAge`: Number of Days (e.g. "7")
- How old is the password?
- `BadPasswordCount`: Number of incorrect passwords (e.g. "3")
- How many incorrect passwords have been entered?
- `NumberOfLogons`: Number of total logons (e.g. "4")
- How many times has the user logged on?

For the `LastLogonTime` property:
> `<[value]`: The property is before the `value` field's date.
>
> `>[value]`: The property is after the `value` field's date.
>
> `[value]`: The property is equal to the `value` field's date. This is the default.
- `LastLogonTime`: Date in format: Monday, January 02, 2006 3:04:05 PM
- If the date is not in that exact format, the check will fail.
- Time **must** be in UTC to pass.

0 comments on commit fe3f105

Please sign in to comment.