Identify anomalies in the password/shadow and group/gshadow data.

def FindAnomalies(self):
    """Identify anomalies in the password/shadow and group/gshadow data."""
    # Find anomalous group entries.
    findings = []
    group_entries = {g.gid for g in itervalues(self.groups)}
    for gid in set(self.gids) - group_entries:
      undefined = ",".join(self.gids.get(gid, []))
      findings.append(
          "gid %d assigned without /etc/groups entry: %s" % (gid, undefined))
    if findings:
      yield self._Anomaly("Accounts with invalid gid.", findings)

    # Find any shared user IDs.
    findings = []
    for uid, names in iteritems(self.uids):
      if len(names) > 1:
        findings.append("uid %d assigned to multiple accounts: %s" %
                        (uid, ",".join(sorted(names))))
    if findings:
      yield self._Anomaly("Accounts with shared uid.", findings)

    # Find privileged groups with unusual members.
    findings = []
    root_grp = self.groups.get("root")
    if root_grp is not None:
      root_members = sorted([m for m in root_grp.members if m != "root"])
      if root_members:
        findings.append("Accounts in 'root' group: %s" % ",".join(root_members))
    if findings:
      yield self._Anomaly("Privileged group with unusual members.", findings)

    # Find accounts without passwd/shadow entries.
    diffs = self.MemberDiff(self.entry, "passwd", self.shadow, "shadow")
    if diffs:
      yield self._Anomaly("Mismatched passwd and shadow files.", diffs)