profile
viewpoint

june-y/calagator 0

An event aggregator based in Portland, OR

june-y/flourish_site 0

The RoR app for Flourish, mobile first automated investment advisor for emerging markets

june-y/Spoon-Knife 0

This repo is for demonstration purposes only.

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 	private final List<Attribute> fileAttributesCache = new ArrayList<Attribute>(); 	private boolean loadedAttributesCacheFromDb = false; +	private final String uidStr;	// SID/uid

Again, this is to distinguish from a numeric UID that already exists.

raman-bt

comment created time in 5 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 public void save() throws TskCoreException { 		} 	} +	/**+	 * Get the uidStr.+	 * +	 * @return String uid. Returns an empty string if no uid is recorded.+	 */+	public String getUidStr() {

The reason we are using the term uidStr is because we already have a numeric UID & GID that we store in files table. There is already a method "int getUid()" in AbstractFile. The "str" suffix was to distinguish between the two.

This uidStr field/column is store the long form string for SIDs.

We kicked around renaming it to ownerUid (still could be confused with the numeric uid) or ownerUidString

raman-bt

comment created time in 5 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

+/*+ * Sleuth Kit Data Model+ *+ * Copyright 2020-2021 Basis Technology Corp.+ * Contact: carrier <at> sleuthkit <dot> org+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+package org.sleuthkit.datamodel;++import java.util.ArrayList;+import java.util.Collection;+import java.util.Collections;+import java.util.List;+import java.util.Optional;+import java.util.Set;++/**+ * Abstracts an OS user account.+ *+ * An OS user account may own files and (some) artifacts.+ *+ */+public final class OsAccount implements Content {++	final static long NO_USER = -1;+	final static String NULL_UID_STR = null;++	private final SleuthkitCase sleuthkitCase;+	+	private final long objId;	+	private final OsAccountRealm realm;		// realm where the username is unique - a domain or a host name, may be null+	private final String loginName;	// user login name - may be null+	private final String uniqueId;	// a unique user sid/uid, may be null+	private final String signature; // something that uniquely identifies this user - either the uniqueId or the realmName/userName.++	private String fullName;	// full name+	private boolean isAdmin = false;	// is admin account.+	private OsAccountType osAccountType = OsAccountType.UNKNOWN;+	private OsAccountStatus osAccountStatus = OsAccountStatus.UNKNOWN;+	private long creationTime = 0;++	private final List<OsAccountAttribute> osAccountAttributes = new ArrayList<>();++	/**+	 * Encapsulates status of an account - whether is it active or disabled or+	 * deleted.+	 */+	public enum OsAccountStatus {+		UNKNOWN(0, "Unknown"),+		ACTIVE(1, "Active"),+		DISABLED(2, "Disabled"),+		DELETED(2, "Deleted");++		private final int id;+		private final String name;++		OsAccountStatus(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account status id.+		 *+		 * @return Account status id.+		 */+		public int getId() {+			return id;+		}++		/**+		 * Get the account status enum name.+		 *+		 * @return+		 */+		String getName() {+			return name;+		}++		/**+		 * Gets account status enum from id.+		 *+		 * @param statusId Id to look for.+		 *+		 * @return Account status enum.+		 */+		public static OsAccountStatus fromID(int statusId) {+			for (OsAccountStatus statusType : OsAccountStatus.values()) {+				if (statusType.ordinal() == statusId) {+					return statusType;+				}+			}+			return null;+		}+	}++	/**+	 * Encapsulates an account type - whether its an interactive login account+	 * or a service account.+	 */+	public enum OsAccountType {+		UNKNOWN(0, "Unknown"),+		SERVICE(1, "Service"),+		INTERACTIVE(2, "Interactive");++		private final int id;+		private final String name;++		OsAccountType(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account type id.+		 *+		 * @return Account type id.+		 */+		int getId() {+			return id;+		}++		/**+		 * Get account type name.+		 *+		 * @return Account type name.+		 */+		String getName() {+			return name;+		}++		/**+		 * Gets account type enum from id.+		 *+		 * @param typeId Id to look for.+		 *+		 * @return Account type enum.+		 */+		public static OsAccountType fromID(int typeId) {+			for (OsAccountType accountType : OsAccountType.values()) {+				if (accountType.ordinal() == typeId) {+					return accountType;+				}+			}+			return null;+		}+	}++	/**+	 * Describes the relationship between an os account instance and the host+	 * where the instance was found.+	 *+	 * Whether an os account actually performed any action on the host or if+	 * just a reference to it was found on the host.+	 */+	public enum OsAccountInstanceType {+		PERFORMED_ACTION_ON(0, "PerformedActionOn"), // the user performed actions on a host+		REFERENCED_ON(1, "ReferencedOn");	// user was simply referenced on a host++		private final int id;+		private final String name;++		OsAccountInstanceType(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account instance type id.+		 *+		 * @return Account instance type id.+		 */+		public int getId() {+			return id;+		}++		/**+		 * Get account instance type name.+		 *+		 * @return Account instance type name.+		 */+		public String getName() {

Is this a display name?

raman-bt

comment created time in 7 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

+/*+ * Sleuth Kit Data Model+ *+ * Copyright 2020-2021 Basis Technology Corp.+ * Contact: carrier <at> sleuthkit <dot> org+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+package org.sleuthkit.datamodel;++import java.util.ArrayList;+import java.util.Collection;+import java.util.Collections;+import java.util.List;+import java.util.Optional;+import java.util.Set;++/**+ * Abstracts an OS user account.+ *+ * An OS user account may own files and (some) artifacts.+ *+ */+public final class OsAccount implements Content {++	final static long NO_USER = -1;+	final static String NULL_UID_STR = null;++	private final SleuthkitCase sleuthkitCase;+	+	private final long objId;	+	private final OsAccountRealm realm;		// realm where the username is unique - a domain or a host name, may be null+	private final String loginName;	// user login name - may be null+	private final String uniqueId;	// a unique user sid/uid, may be null+	private final String signature; // something that uniquely identifies this user - either the uniqueId or the realmName/userName.++	private String fullName;	// full name+	private boolean isAdmin = false;	// is admin account.+	private OsAccountType osAccountType = OsAccountType.UNKNOWN;+	private OsAccountStatus osAccountStatus = OsAccountStatus.UNKNOWN;+	private long creationTime = 0;++	private final List<OsAccountAttribute> osAccountAttributes = new ArrayList<>();++	/**+	 * Encapsulates status of an account - whether is it active or disabled or+	 * deleted.+	 */+	public enum OsAccountStatus {+		UNKNOWN(0, "Unknown"),+		ACTIVE(1, "Active"),+		DISABLED(2, "Disabled"),+		DELETED(2, "Deleted");++		private final int id;+		private final String name;++		OsAccountStatus(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account status id.+		 *+		 * @return Account status id.+		 */+		public int getId() {+			return id;+		}++		/**+		 * Get the account status enum name.+		 *+		 * @return+		 */+		String getName() {+			return name;+		}++		/**+		 * Gets account status enum from id.+		 *+		 * @param statusId Id to look for.+		 *+		 * @return Account status enum.+		 */+		public static OsAccountStatus fromID(int statusId) {+			for (OsAccountStatus statusType : OsAccountStatus.values()) {+				if (statusType.ordinal() == statusId) {+					return statusType;+				}+			}+			return null;+		}+	}++	/**+	 * Encapsulates an account type - whether its an interactive login account+	 * or a service account.+	 */+	public enum OsAccountType {+		UNKNOWN(0, "Unknown"),+		SERVICE(1, "Service"),+		INTERACTIVE(2, "Interactive");++		private final int id;+		private final String name;++		OsAccountType(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account type id.+		 *+		 * @return Account type id.+		 */+		int getId() {+			return id;+		}++		/**+		 * Get account type name.+		 *+		 * @return Account type name.+		 */+		String getName() {

Is this a display name?

raman-bt

comment created time in 7 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

+/*+ * Sleuth Kit Data Model+ *+ * Copyright 2020-2021 Basis Technology Corp.+ * Contact: carrier <at> sleuthkit <dot> org+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+package org.sleuthkit.datamodel;++import java.util.ArrayList;+import java.util.Collection;+import java.util.Collections;+import java.util.List;+import java.util.Optional;+import java.util.Set;++/**+ * Abstracts an OS user account.+ *+ * An OS user account may own files and (some) artifacts.+ *+ */+public final class OsAccount implements Content {++	final static long NO_USER = -1;+	final static String NULL_UID_STR = null;++	private final SleuthkitCase sleuthkitCase;+	+	private final long objId;	+	private final OsAccountRealm realm;		// realm where the username is unique - a domain or a host name, may be null+	private final String loginName;	// user login name - may be null+	private final String uniqueId;	// a unique user sid/uid, may be null+	private final String signature; // something that uniquely identifies this user - either the uniqueId or the realmName/userName.++	private String fullName;	// full name+	private boolean isAdmin = false;	// is admin account.+	private OsAccountType osAccountType = OsAccountType.UNKNOWN;+	private OsAccountStatus osAccountStatus = OsAccountStatus.UNKNOWN;+	private long creationTime = 0;++	private final List<OsAccountAttribute> osAccountAttributes = new ArrayList<>();++	/**+	 * Encapsulates status of an account - whether is it active or disabled or+	 * deleted.+	 */+	public enum OsAccountStatus {+		UNKNOWN(0, "Unknown"),+		ACTIVE(1, "Active"),+		DISABLED(2, "Disabled"),+		DELETED(2, "Deleted");++		private final int id;+		private final String name;++		OsAccountStatus(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account status id.+		 *+		 * @return Account status id.+		 */+		public int getId() {+			return id;+		}++		/**+		 * Get the account status enum name.+		 *+		 * @return+		 */+		String getName() {+			return name;+		}++		/**+		 * Gets account status enum from id.+		 *+		 * @param statusId Id to look for.+		 *+		 * @return Account status enum.+		 */+		public static OsAccountStatus fromID(int statusId) {+			for (OsAccountStatus statusType : OsAccountStatus.values()) {+				if (statusType.ordinal() == statusId) {+					return statusType;+				}+			}+			return null;+		}+	}++	/**+	 * Encapsulates an account type - whether its an interactive login account+	 * or a service account.+	 */+	public enum OsAccountType {+		UNKNOWN(0, "Unknown"),+		SERVICE(1, "Service"),+		INTERACTIVE(2, "Interactive");++		private final int id;+		private final String name;++		OsAccountType(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account type id.+		 *+		 * @return Account type id.+		 */+		int getId() {+			return id;+		}++		/**+		 * Get account type name.+		 *+		 * @return Account type name.+		 */+		String getName() {+			return name;+		}++		/**+		 * Gets account type enum from id.+		 *+		 * @param typeId Id to look for.+		 *+		 * @return Account type enum.+		 */+		public static OsAccountType fromID(int typeId) {+			for (OsAccountType accountType : OsAccountType.values()) {+				if (accountType.ordinal() == typeId) {+					return accountType;+				}+			}+			return null;+		}+	}++	/**+	 * Describes the relationship between an os account instance and the host+	 * where the instance was found.+	 *+	 * Whether an os account actually performed any action on the host or if+	 * just a reference to it was found on the host.+	 */+	public enum OsAccountInstanceType {+		PERFORMED_ACTION_ON(0, "PerformedActionOn"), // the user performed actions on a host+		REFERENCED_ON(1, "ReferencedOn");	// user was simply referenced on a host

@bcarrier Do we want these to be display names in sentence case?

raman-bt

comment created time in 7 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

+/*+ * Sleuth Kit Data Model+ *+ * Copyright 2020-2021 Basis Technology Corp.+ * Contact: carrier <at> sleuthkit <dot> org+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+package org.sleuthkit.datamodel;++import java.util.ArrayList;+import java.util.Collection;+import java.util.Collections;+import java.util.List;+import java.util.Optional;+import java.util.Set;++/**+ * Abstracts an OS user account.+ *+ * An OS user account may own files and (some) artifacts.+ *+ */+public final class OsAccount implements Content {++	final static long NO_USER = -1;+	final static String NULL_UID_STR = null;++	private final SleuthkitCase sleuthkitCase;+	+	private final long objId;	+	private final OsAccountRealm realm;		// realm where the username is unique - a domain or a host name, may be null+	private final String loginName;	// user login name - may be null+	private final String uniqueId;	// a unique user sid/uid, may be null+	private final String signature; // something that uniquely identifies this user - either the uniqueId or the realmName/userName.++	private String fullName;	// full name+	private boolean isAdmin = false;	// is admin account.+	private OsAccountType osAccountType = OsAccountType.UNKNOWN;+	private OsAccountStatus osAccountStatus = OsAccountStatus.UNKNOWN;+	private long creationTime = 0;++	private final List<OsAccountAttribute> osAccountAttributes = new ArrayList<>();++	/**+	 * Encapsulates status of an account - whether is it active or disabled or+	 * deleted.+	 */+	public enum OsAccountStatus {+		UNKNOWN(0, "Unknown"),+		ACTIVE(1, "Active"),+		DISABLED(2, "Disabled"),+		DELETED(2, "Deleted");++		private final int id;+		private final String name;++		OsAccountStatus(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account status id.+		 *+		 * @return Account status id.+		 */+		public int getId() {+			return id;+		}++		/**+		 * Get the account status enum name.+		 *+		 * @return+		 */+		String getName() {+			return name;+		}++		/**+		 * Gets account status enum from id.+		 *+		 * @param statusId Id to look for.+		 *+		 * @return Account status enum.+		 */+		public static OsAccountStatus fromID(int statusId) {+			for (OsAccountStatus statusType : OsAccountStatus.values()) {+				if (statusType.ordinal() == statusId) {+					return statusType;+				}+			}+			return null;+		}+	}++	/**+	 * Encapsulates an account type - whether its an interactive login account+	 * or a service account.+	 */+	public enum OsAccountType {+		UNKNOWN(0, "Unknown"),+		SERVICE(1, "Service"),+		INTERACTIVE(2, "Interactive");++		private final int id;+		private final String name;++		OsAccountType(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account type id.+		 *+		 * @return Account type id.+		 */+		int getId() {+			return id;+		}++		/**+		 * Get account type name.+		 *+		 * @return Account type name.+		 */+		String getName() {+			return name;+		}++		/**+		 * Gets account type enum from id.+		 *+		 * @param typeId Id to look for.+		 *+		 * @return Account type enum.+		 */+		public static OsAccountType fromID(int typeId) {+			for (OsAccountType accountType : OsAccountType.values()) {+				if (accountType.ordinal() == typeId) {+					return accountType;+				}+			}+			return null;+		}+	}++	/**+	 * Describes the relationship between an os account instance and the host+	 * where the instance was found.+	 *+	 * Whether an os account actually performed any action on the host or if+	 * just a reference to it was found on the host.+	 */+	public enum OsAccountInstanceType {+		PERFORMED_ACTION_ON(0, "PerformedActionOn"), // the user performed actions on a host+		REFERENCED_ON(1, "ReferencedOn");	// user was simply referenced on a host++		private final int id;+		private final String name;++		OsAccountInstanceType(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account instance type id.+		 *+		 * @return Account instance type id.+		 */+		public int getId() {+			return id;+		}++		/**+		 * Get account instance type name.+		 *+		 * @return Account instance type name.+		 */+		public String getName() {+			return name;+		}++		/**+		 * Gets account instance type enum from id.+		 *+		 * @param typeId Id to look for.+		 *+		 * @return Account instance type enum.+		 */+		public static OsAccountInstanceType fromID(int typeId) {+			for (OsAccountInstanceType statusType : OsAccountInstanceType.values()) {+				if (statusType.ordinal() == typeId) {+					return statusType;+				}+			}+			return null;+		}+	}++	/**+	 * Constructs an OsAccount with a realm/username and unique id, and+	 * signature+	 */

Incomplete doc. Important, since realm can be null, for example.

raman-bt

comment created time in 7 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

+/*+ * Sleuth Kit Data Model+ *+ * Copyright 2020-2021 Basis Technology Corp.+ * Contact: carrier <at> sleuthkit <dot> org+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+package org.sleuthkit.datamodel;++import java.util.ArrayList;+import java.util.Collection;+import java.util.Collections;+import java.util.List;+import java.util.Optional;+import java.util.Set;++/**+ * Abstracts an OS user account.+ *+ * An OS user account may own files and (some) artifacts.+ *+ */+public final class OsAccount implements Content {++	final static long NO_USER = -1;+	final static String NULL_UID_STR = null;++	private final SleuthkitCase sleuthkitCase;+	+	private final long objId;	+	private final OsAccountRealm realm;		// realm where the username is unique - a domain or a host name, may be null+	private final String loginName;	// user login name - may be null+	private final String uniqueId;	// a unique user sid/uid, may be null+	private final String signature; // something that uniquely identifies this user - either the uniqueId or the realmName/userName.++	private String fullName;	// full name+	private boolean isAdmin = false;	// is admin account.+	private OsAccountType osAccountType = OsAccountType.UNKNOWN;+	private OsAccountStatus osAccountStatus = OsAccountStatus.UNKNOWN;+	private long creationTime = 0;++	private final List<OsAccountAttribute> osAccountAttributes = new ArrayList<>();++	/**+	 * Encapsulates status of an account - whether is it active or disabled or+	 * deleted.+	 */+	public enum OsAccountStatus {+		UNKNOWN(0, "Unknown"),+		ACTIVE(1, "Active"),+		DISABLED(2, "Disabled"),+		DELETED(2, "Deleted");++		private final int id;+		private final String name;++		OsAccountStatus(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account status id.+		 *+		 * @return Account status id.+		 */+		public int getId() {+			return id;+		}++		/**+		 * Get the account status enum name.+		 *+		 * @return+		 */+		String getName() {+			return name;+		}++		/**+		 * Gets account status enum from id.+		 *+		 * @param statusId Id to look for.+		 *+		 * @return Account status enum.+		 */+		public static OsAccountStatus fromID(int statusId) {+			for (OsAccountStatus statusType : OsAccountStatus.values()) {+				if (statusType.ordinal() == statusId) {+					return statusType;+				}+			}+			return null;+		}+	}++	/**+	 * Encapsulates an account type - whether its an interactive login account+	 * or a service account.+	 */+	public enum OsAccountType {+		UNKNOWN(0, "Unknown"),+		SERVICE(1, "Service"),+		INTERACTIVE(2, "Interactive");++		private final int id;+		private final String name;++		OsAccountType(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account type id.+		 *+		 * @return Account type id.+		 */+		int getId() {+			return id;+		}++		/**+		 * Get account type name.+		 *+		 * @return Account type name.+		 */+		String getName() {+			return name;+		}++		/**+		 * Gets account type enum from id.+		 *+		 * @param typeId Id to look for.+		 *+		 * @return Account type enum.+		 */+		public static OsAccountType fromID(int typeId) {+			for (OsAccountType accountType : OsAccountType.values()) {+				if (accountType.ordinal() == typeId) {+					return accountType;+				}+			}+			return null;+		}+	}++	/**+	 * Describes the relationship between an os account instance and the host+	 * where the instance was found.+	 *+	 * Whether an os account actually performed any action on the host or if+	 * just a reference to it was found on the host.+	 */+	public enum OsAccountInstanceType {+		PERFORMED_ACTION_ON(0, "PerformedActionOn"), // the user performed actions on a host+		REFERENCED_ON(1, "ReferencedOn");	// user was simply referenced on a host++		private final int id;+		private final String name;++		OsAccountInstanceType(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account instance type id.+		 *+		 * @return Account instance type id.+		 */+		public int getId() {+			return id;+		}++		/**+		 * Get account instance type name.+		 *+		 * @return Account instance type name.+		 */+		public String getName() {+			return name;+		}++		/**+		 * Gets account instance type enum from id.+		 *+		 * @param typeId Id to look for.+		 *+		 * @return Account instance type enum.+		 */+		public static OsAccountInstanceType fromID(int typeId) {+			for (OsAccountInstanceType statusType : OsAccountInstanceType.values()) {+				if (statusType.ordinal() == typeId) {+					return statusType;+				}+			}+			return null;+		}+	}++	/**+	 * Constructs an OsAccount with a realm/username and unique id, and+	 * signature+	 */+	OsAccount(SleuthkitCase sleuthkitCase, long objId, OsAccountRealm realm, String loginName, String uniqueId, String signature) {+

@bcarrier Will we always have an OsAccountRealm object when we construct an OsAccount?

raman-bt

comment created time in 6 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

+/*+ * Sleuth Kit Data Model+ *+ * Copyright 2020-2021 Basis Technology Corp.+ * Contact: carrier <at> sleuthkit <dot> org+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+package org.sleuthkit.datamodel;++import java.util.ArrayList;+import java.util.Collection;+import java.util.Collections;+import java.util.List;+import java.util.Optional;+import java.util.Set;++/**+ * Abstracts an OS user account.+ *+ * An OS user account may own files and (some) artifacts.+ *+ */+public final class OsAccount implements Content {++	final static long NO_USER = -1;+	final static String NULL_UID_STR = null;++	private final SleuthkitCase sleuthkitCase;+	+	private final long objId;	+	private final OsAccountRealm realm;		// realm where the username is unique - a domain or a host name, may be null+	private final String loginName;	// user login name - may be null+	private final String uniqueId;	// a unique user sid/uid, may be null+	private final String signature; // something that uniquely identifies this user - either the uniqueId or the realmName/userName.++	private String fullName;	// full name+	private boolean isAdmin = false;	// is admin account.+	private OsAccountType osAccountType = OsAccountType.UNKNOWN;+	private OsAccountStatus osAccountStatus = OsAccountStatus.UNKNOWN;+	private long creationTime = 0;++	private final List<OsAccountAttribute> osAccountAttributes = new ArrayList<>();++	/**+	 * Encapsulates status of an account - whether is it active or disabled or+	 * deleted.+	 */+	public enum OsAccountStatus {+		UNKNOWN(0, "Unknown"),+		ACTIVE(1, "Active"),+		DISABLED(2, "Disabled"),+		DELETED(2, "Deleted");++		private final int id;+		private final String name;++		OsAccountStatus(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account status id.+		 *+		 * @return Account status id.+		 */+		public int getId() {+			return id;+		}++		/**+		 * Get the account status enum name.+		 *+		 * @return+		 */+		String getName() {+			return name;+		}++		/**+		 * Gets account status enum from id.+		 *+		 * @param statusId Id to look for.+		 *+		 * @return Account status enum.+		 */+		public static OsAccountStatus fromID(int statusId) {+			for (OsAccountStatus statusType : OsAccountStatus.values()) {+				if (statusType.ordinal() == statusId) {+					return statusType;+				}+			}+			return null;+		}+	}++	/**+	 * Encapsulates an account type - whether its an interactive login account+	 * or a service account.+	 */+	public enum OsAccountType {+		UNKNOWN(0, "Unknown"),+		SERVICE(1, "Service"),+		INTERACTIVE(2, "Interactive");++		private final int id;+		private final String name;++		OsAccountType(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account type id.+		 *+		 * @return Account type id.+		 */+		int getId() {+			return id;+		}++		/**+		 * Get account type name.+		 *+		 * @return Account type name.+		 */+		String getName() {+			return name;+		}++		/**+		 * Gets account type enum from id.+		 *+		 * @param typeId Id to look for.+		 *+		 * @return Account type enum.+		 */+		public static OsAccountType fromID(int typeId) {+			for (OsAccountType accountType : OsAccountType.values()) {+				if (accountType.ordinal() == typeId) {+					return accountType;+				}+			}+			return null;+		}+	}++	/**+	 * Describes the relationship between an os account instance and the host+	 * where the instance was found.+	 *+	 * Whether an os account actually performed any action on the host or if+	 * just a reference to it was found on the host.+	 */+	public enum OsAccountInstanceType {+		PERFORMED_ACTION_ON(0, "PerformedActionOn"), // the user performed actions on a host+		REFERENCED_ON(1, "ReferencedOn");	// user was simply referenced on a host++		private final int id;+		private final String name;++		OsAccountInstanceType(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account instance type id.+		 *+		 * @return Account instance type id.+		 */+		public int getId() {+			return id;+		}++		/**+		 * Get account instance type name.+		 *+		 * @return Account instance type name.+		 */+		public String getName() {+			return name;+		}++		/**+		 * Gets account instance type enum from id.+		 *+		 * @param typeId Id to look for.+		 *+		 * @return Account instance type enum.+		 */+		public static OsAccountInstanceType fromID(int typeId) {+			for (OsAccountInstanceType statusType : OsAccountInstanceType.values()) {+				if (statusType.ordinal() == typeId) {+					return statusType;+				}+			}+			return null;+		}+	}++	/**+	 * Constructs an OsAccount with a realm/username and unique id, and+	 * signature+	 */+	OsAccount(SleuthkitCase sleuthkitCase, long objId, OsAccountRealm realm, String loginName, String uniqueId, String signature) {++		this.sleuthkitCase = sleuthkitCase;+		+		this.objId = objId;+		this.realm = realm;+		this.loginName = loginName;+		this.uniqueId = uniqueId;+		this.signature = signature;+	}++	/**+	 * Sets the account user's full name.+	 *+	 * @param fullName Full name.+	 */+	public void setFullName(String fullName) {+		this.fullName = fullName;+	}++	/**+	 * Sets the admin flag for the account.+	 *+	 * @param isAdmin Flag to indicate if the account is an admin account.+	 */+	public void setIsAdmin(boolean isAdmin) {+		this.isAdmin = isAdmin;+	}++	/**+	 * Sets account type for the account.+	 *+	 * @param osAccountType Account type..+	 */+	public void setOsAccountType(OsAccountType osAccountType) {+		this.osAccountType = osAccountType;+	}++	/**+	 * Sets account status for the account.+	 *+	 * @param osAccountStatus Account status.+	 */+	public void setOsAccountStatus(OsAccountStatus osAccountStatus) {+		this.osAccountStatus = osAccountStatus;+	}++	/**+	 * Set account creation time.+	 *+	 * @param creationTime Creation time.+	 */+	public void setCreationTime(long creationTime) {+		this.creationTime = creationTime;+	}++	/**+	 * Adds account attributes to the account.+	 *+	 * @param osAccountAttributes Collection of  attributes to add.+	 */+	void addAttributes(Set<OsAccountAttribute> osAccountAttributes) throws TskCoreException {+		sleuthkitCase.getOsAccountManager().addOsAccountAttributes(this, osAccountAttributes);+		osAccountAttributes.addAll(osAccountAttributes);+	}++	/**+	 * Get the account id.+	 *+	 * @return Account id.+	 */+	public long getId() {+		return objId;+	}++	/**+	 * Get the unique identifier for the account. +	 * The id is unique within the account realm.+	 *+	 * @return Optional unique identifier.+	 */+	public Optional<String> getUniqueIdWithinRealm() {+		return Optional.ofNullable(uniqueId);+	}++	/**+	 * Get the account signature.+	 *+	 * @return Account signature.+	 */+	public String getSignature() {+		return signature;+	}++	/**+	 * Get the account realm.+	 *+	 * @return Optional account realm.+	 */+	public Optional<OsAccountRealm> getRealm() {+		return Optional.ofNullable(realm);+	}++	/**+	 * Get account login name.+	 *+	 * @return Optional login name.+	 */+	public Optional<String> getLoginName() {+		return Optional.ofNullable(loginName);+	}++	/**+	 * Get account user full name.+	 *+	 * @return Optional with full name.+	 */+	public Optional<String> getFullName() {+		return Optional.ofNullable(fullName);+	}++	/**+	 * Check if account is an admin account.+	 *+	 * @return True if account is an admin account, false otherwise.+	 */+	public boolean isIsAdmin() {

Just isAdmin() would be better, I think.

raman-bt

comment created time in 6 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

+/*+ * Sleuth Kit Data Model+ *+ * Copyright 2020-2021 Basis Technology Corp.+ * Contact: carrier <at> sleuthkit <dot> org+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+package org.sleuthkit.datamodel;++import java.util.ArrayList;+import java.util.Collection;+import java.util.Collections;+import java.util.List;+import java.util.Optional;+import java.util.Set;++/**+ * Abstracts an OS user account.+ *+ * An OS user account may own files and (some) artifacts.+ *+ */+public final class OsAccount implements Content {++	final static long NO_USER = -1;+	final static String NULL_UID_STR = null;++	private final SleuthkitCase sleuthkitCase;+	+	private final long objId;	+	private final OsAccountRealm realm;		// realm where the username is unique - a domain or a host name, may be null+	private final String loginName;	// user login name - may be null+	private final String uniqueId;	// a unique user sid/uid, may be null+	private final String signature; // something that uniquely identifies this user - either the uniqueId or the realmName/userName.++	private String fullName;	// full name

@bcarrier OsAccount has mutable state, e.g., full name, but I don't see any APIs for persisting state changes to the case database in OsAccountManager or any code in the setters to persist changes.

raman-bt

comment created time in 6 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

+/*+ * Sleuth Kit Data Model+ *+ * Copyright 2020 Basis Technology Corp.+ * Contact: carrier <at> sleuthkit <dot> org+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+package org.sleuthkit.datamodel;++import com.google.common.base.Strings;+import java.sql.PreparedStatement;+import java.sql.ResultSet;+import java.sql.SQLException;+import java.sql.Statement;+import java.util.HashSet;+import java.util.Objects;+import java.util.Set;+import java.util.logging.Level;+import java.util.logging.Logger;+import org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE;+import org.sleuthkit.datamodel.SleuthkitCase.CaseDbConnection;+import org.sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction;++/**+ * Responsible for creating/updating/retrieving the OS user accounts for files+ * and artifacts.+ *+ */+public final class OsAccountManager {++	private static final Logger LOGGER = Logger.getLogger(OsAccountManager.class.getName());++	private final SleuthkitCase db;++	/**+	 * Construct a OsUserManager for the given SleuthkitCase.+	 *+	 * @param skCase The SleuthkitCase+	 *+	 */+	OsAccountManager(SleuthkitCase skCase) {+		this.db = skCase;+	}++	/**+	 * Gets or creates a OS user account with given unique id or given user name+	 * for the given data source.+	 *+	 * @param uniqueAccountId User sid/uid.+	 * @param loginName       User login name.+	 * @param realmName       Realm within which the accountId/userName is+	 *                        unique.+	 * @param host			  Host for the realm, may be null.+	 * @param transaction     Transaction to use for database operation.+	 *+	 * @return Row id of the row matching the given user id and data source.+	 */+	OsAccount getOrCreateOsAccount(String uniqueAccountId, String loginName, String realmName, Host host, CaseDbTransaction transaction) throws TskCoreException {++		// ensure at least one of the two is supplied - unique id or a login name+		if (Strings.isNullOrEmpty(uniqueAccountId) && Strings.isNullOrEmpty(loginName)) {+			throw new IllegalArgumentException("Cannot create OS User with both uniqueId and loginName as null.");+		}++		CaseDbConnection connection = transaction.getConnection();++		OsAccount osAccount = null;+		// First search for user by uniqueId+		if (!Strings.isNullOrEmpty(uniqueAccountId)) {+			osAccount = getOsAccountByUniqueId(uniqueAccountId, host, connection);+			if (osAccount != null) {+				return osAccount;+			}+		}++		// get/create the realm with given name+		OsAccountRealm realm = null;+		if (Strings.isNullOrEmpty(realmName) == false) {+			realm = db.getOsAccountRealmManager().getOrCreateRealmByName(realmName, host, transaction);+		}+			+		// search by loginName+		if (!Strings.isNullOrEmpty(loginName)) {+			osAccount = getOsAccountByLoginName(loginName, realm, connection);+			if (osAccount != null) {+				return osAccount;+			}+		}++		// couldn't find it, create a new account+		return createOsAccount(uniqueAccountId, loginName, realm, connection);++	}++	/**+	 * Creates a user with the given uid, name, and realm.+	 *+	 * @param uniqueId     User sid/uid. May be null/empty.+	 * @param loginName    User name. may be null or empty.+	 * @param realm	       Realm. May be null.+	 * @param connection   Database connection to use.+	 *+	 * @return OS account.+	 *+	 * @throws TskCoreException+	 */+	private OsAccount createOsAccount(String uniqueId, String loginName, OsAccountRealm realm, CaseDbConnection connection) throws TskCoreException {++		String signature;+		if (Strings.isNullOrEmpty(uniqueId) == false) {+			signature = uniqueId;+		} else {+			if (Objects.isNull(realm)) {+				signature = loginName;+			} else {+				signature = String.format("%s/%s", realm.getName(), loginName);+			}+		}++		db.acquireSingleUserCaseWriteLock();+		try {+			+			// first create a tsk_object for the OsAccount.+			+			// RAMAN TBD: need to get the correct parnt obj id.  +			//            Create an Object Directory parent and used its id.+			// RAMAN TBD: what is the object type ??+			+			long parentObjId = 1;+			int objTypeId = TskData.ObjectType.ARTIFACT.getObjectType();+			+			long objId = db.addObject(parentObjId, objTypeId, connection);+			+			String userInsertSQL = "INSERT INTO tsk_os_accounts(obj_id, login_name, realm_id, unique_id, signature)"+					+ " VALUES (?, ?, ?, ?, ?)"; // NON-NLS++			PreparedStatement preparedStatement = connection.getPreparedStatement(userInsertSQL, Statement.NO_GENERATED_KEYS);+			preparedStatement.clearParameters();++			preparedStatement.setLong(1, objId);+			+			preparedStatement.setString(2, loginName);+			if (!Objects.isNull(realm)) {+				preparedStatement.setLong(3, realm.getId());+			} else {+				preparedStatement.setNull(3, java.sql.Types.BIGINT);+			}++			preparedStatement.setString(4, uniqueId);+			preparedStatement.setString(5, signature);++			connection.executeUpdate(preparedStatement);++			return new OsAccount(db, objId, realm, loginName, uniqueId, signature);+			+		} catch (SQLException ex) {+			LOGGER.log(Level.SEVERE, null, ex);+			throw new TskCoreException(String.format("Error adding OS user account with uniqueId = %s, userName = %s", uniqueId, loginName), ex);+		} finally {+			db.releaseSingleUserCaseWriteLock();+		}+	}++	/**+	 * Get the OsUser with the given unique user id.+	 *+	 * @param uniqueId User sid/uid.+	 * @param host     Host for account realm, may be null.+	 *+	 * @return OsUser.+	 *+	 * @throws TskCoreException         If there is an error getting the user.+	 * @throws IllegalArgumentException If no matching user is found.+	 */+	public OsAccount getOsAccount(String uniqueId, Host host) throws TskCoreException {++		try (CaseDbConnection connection = this.db.getConnection()) {++			OsAccount osAccount = getOsAccountByUniqueId(uniqueId, host, connection);+			if (osAccount == null) {+				throw new IllegalArgumentException(String.format("No user found with id %s ", uniqueId));+			}++			return osAccount;+		}+	}++	/**+	 * Gets a user by the uniqueId. Returns null if no matching user is found.+	 *+	 * @param uniqueId Account SID/uid.+	 * @param Host Host to match the realm, may be null.+	 * @param connection Database connection to use.+	 *+	 * @return OsUser, null if no user with matching uniqueId is found.+	 *+	 * @throws TskCoreException+	 */+	private OsAccount getOsAccountByUniqueId(String uniqueId, Host host, CaseDbConnection connection) throws TskCoreException {++		String whereHostClause = (host == null) +							? " realms.host_id IS NULL " +							: " realms.host_id = " + host.getId() + " ";+		String queryString = "SELECT accounts.obj_id as obj_id, accounts.login_name, accounts.full_name, "+								+ " accounts.realm_id, accounts.unique_id, accounts.signature, "+								+ "	accounts.type, accounts.status, accounts.admin, accounts.creation_date_time, "+								+ " realms.name as realm_name, realms.unique_id as realm_unique_id, realms.host_id, realms.name_type "+							+ " FROM tsk_os_accounts as accounts"+							+ "		LEFT JOIN tsk_os_account_realms as realms"+							+ " ON accounts.realm_id = realms.id"+							+ " WHERE " + whereHostClause+							+ "		AND LOWER(accounts.unique_id) = LOWER('" + uniqueId + "')";+		+		try (Statement s = connection.createStatement();+				ResultSet rs = connection.executeQuery(s, queryString)) {++			if (!rs.next()) {+				return null;	// no match found+			} else {+				OsAccountRealm realm = null;+				long realmId = rs.getLong("realm_id");+				if (!rs.wasNull()) {+					realm = new OsAccountRealm(realmId, rs.getString("realm_name"), +									OsAccountRealm.RealmNameType.fromID(rs.getInt("name_type")), +									rs.getString("realm_unique_id"), host );+				}++				return osAccountFromResultSet(rs, realm);+			}+		} catch (SQLException ex) {+			throw new TskCoreException(String.format("Error getting OS user account for unique id = %s", uniqueId), ex);+		}+	}++	/**+	 * Gets a user by the realm/userName. Returns null if no matching user is+	 * found.+	 *+	 * @param loginName    User login name.+	 * @param realm	       Account Realm, may be null.+	 * @param connection   Database connection to use.+	 *+	 * @return OsUser, null if no user with matching uniqueId is found.+	 *+	 * @throws TskCoreException+	 */+	private OsAccount getOsAccountByLoginName(String loginName, OsAccountRealm realm, CaseDbConnection connection) throws TskCoreException {++		String queryString = "SELECT * FROM tsk_os_accounts"+				+ " WHERE LOWER(login_name) = LOWER('" + loginName + "')";+		+		if (realm != null) {+				queryString += " AND realm_id = " + realm.getId();+		}++		try (Statement s = connection.createStatement();+				ResultSet rs = connection.executeQuery(s, queryString)) {++			if (!rs.next()) {+				return null;	// no match found+			} else {+				return osAccountFromResultSet(rs, realm);+			}+		} catch (SQLException ex) {+			throw new TskCoreException(String.format("Error getting OS user account for realm = %s and loginName = %s.", (realm != null) ? realm.getName() : "NULL", loginName), ex);+		}+	}++	/**+	 * Get the OsAccount with the given object id.+	 *+	 * @param objId Obj id for the user account.+	 *+	 * @return OsAccount.+	 *+	 * @throws TskCoreException         If there is an error getting the user.+	 * @throws IllegalArgumentException If no matching user is found.+	 */+	public OsAccount getOsAccount(long objId) throws TskCoreException {++		try (CaseDbConnection connection = this.db.getConnection()) {+			return getOsAccount(objId, connection);+		}+	}+	+	/**+	 * Get the OsAccount with the given row id.+	 *+	 * @param objId Object id for the user account.+	 * @param connection Database connection to use.+	 *+	 * @return OsAccount.+	 *+	 * @throws TskCoreException         If there is an error getting the user.+	 * @throws IllegalArgumentException If no matching user is found.+	 */+	private OsAccount getOsAccount(long objId, CaseDbConnection connection) throws TskCoreException {++		String queryString = "SELECT * FROM tsk_os_accounts"+				+ " WHERE obj_id = " + objId;++		try (	Statement s = connection.createStatement();+				ResultSet rs = connection.executeQuery(s, queryString)) {++			if (!rs.next()) {+				throw new IllegalArgumentException(String.format("No user found with obj id = %d ", objId));+			} else {+		+				OsAccountRealm realm = null;+				long realmId = rs.getLong("realm_id");++				if (!rs.wasNull()) {+					realm = db.getOsAccountRealmManager().getRealm(realmId, connection);+				}++				return osAccountFromResultSet(rs, realm);+			}+		} catch (SQLException ex) {+			throw new TskCoreException("Error getting OS user account ", ex);+		}+	}+	+	/**+	 * Adds a row to the tsk_os_account_instances table.+	 *+	 * @param osAccount Account.+	 * @param host     Host on which the instance is found.+	 * @param dataSourceObjId Object id of the data source where the instance is found.+	 * @param instanceType Instance type.+	 * @param connection   Database connection to use.+	 *+	 * @throws TskCoreException+	 */+	void addOsAccountInstance(OsAccount osAccount, Host host, long dataSourceObjId, OsAccount.OsAccountInstanceType instanceType, CaseDbConnection connection) throws TskCoreException {++		db.acquireSingleUserCaseWriteLock();+		try {+			String userInsertSQL = "INSERT INTO tsk_os_account_instances(os_account_id, data_source_obj_id, host_id, instance_type)"+					+ " VALUES (?, ?, ?, ?)"; // NON-NLS++			PreparedStatement preparedStatement = connection.getPreparedStatement(userInsertSQL, Statement.RETURN_GENERATED_KEYS);+			preparedStatement.clearParameters();++			preparedStatement.setLong(1, osAccount.getId());+			preparedStatement.setLong(2, dataSourceObjId);+			preparedStatement.setLong(3, host.getId());+			preparedStatement.setInt(4, instanceType.getId());+			+			connection.executeUpdate(preparedStatement);+			+		} catch (SQLException ex) {+			LOGGER.log(Level.SEVERE, null, ex);+			throw new TskCoreException(String.format("Error adding os account instance for account = %s, host name = %s, data source object id = %d", osAccount.getSignature(), host.getName(), dataSourceObjId ), ex);+		} finally {+			db.releaseSingleUserCaseWriteLock();+		}+	}+	+	/**+	 * Get all accounts that had an instance on the specified host.+	 * +	 * @param host Host for which to look accounts for.+	 * +	 * @return Set of OsAccounts, may be empty.+	 */+	Set<OsAccount>  getAcccounts(Host host) throws TskCoreException {+	+		String queryString = "SELECT * FROM tsk_os_accounts as accounts "+				+ " JOIN tsk_os_account_instances as instances "+				+ " ON instances.os_account_id = accounts.obj_id "+				+ " WHERE instances.host_id = " + host.getId();++		try (CaseDbConnection connection = this.db.getConnection();+				Statement s = connection.createStatement();+				ResultSet rs = connection.executeQuery(s, queryString)) {++			Set<OsAccount> accounts = new HashSet<>();+			while (rs.next()) {+				OsAccountRealm realm = null;+				long realmId = rs.getLong("realm_id");+				if (!rs.wasNull()) {+					realm = db.getOsAccountRealmManager().getRealm(realmId, connection);+				}++				accounts.add(osAccountFromResultSet(rs, realm));+			} +			return accounts;+		} catch (SQLException ex) {+			throw new TskCoreException(String.format("Error getting OS accounts for host id = %d", host.getId()), ex);+		}+	}+	+	+	/**+	 * Gets or creates an OS account with the given SID.+	 * +	 * @param sid Account SID.+	 * @param host Host for the realm.+	 * @param transaction Transaction to use.+	 * +	 * @return OsAccount for the user.+	 * @throws TskCoreException +	 */+	OsAccount getOrCreateOsAccountByWindowsSID(String sid, Host host, CaseDbTransaction transaction) throws TskCoreException {

@bcarrier This method has a check then act race condition for multi-user cases or in multithreaded scenarios.

What if the user does not have a Windows SID?

raman-bt

comment created time in 6 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

+/*+ * Sleuth Kit Data Model+ *+ * Copyright 2020-2021 Basis Technology Corp.+ * Contact: carrier <at> sleuthkit <dot> org+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+package org.sleuthkit.datamodel;++import java.util.ArrayList;+import java.util.Collection;+import java.util.Collections;+import java.util.List;+import java.util.Optional;+import java.util.Set;++/**+ * Abstracts an OS user account.+ *+ * An OS user account may own files and (some) artifacts.+ *+ */+public final class OsAccount implements Content {++	final static long NO_USER = -1;+	final static String NULL_UID_STR = null;++	private final SleuthkitCase sleuthkitCase;+	+	private final long objId;	+	private final OsAccountRealm realm;		// realm where the username is unique - a domain or a host name, may be null+	private final String loginName;	// user login name - may be null+	private final String uniqueId;	// a unique user sid/uid, may be null+	private final String signature; // something that uniquely identifies this user - either the uniqueId or the realmName/userName.++	private String fullName;	// full name+	private boolean isAdmin = false;	// is admin account.+	private OsAccountType osAccountType = OsAccountType.UNKNOWN;+	private OsAccountStatus osAccountStatus = OsAccountStatus.UNKNOWN;+	private long creationTime = 0;++	private final List<OsAccountAttribute> osAccountAttributes = new ArrayList<>();++	/**+	 * Encapsulates status of an account - whether is it active or disabled or+	 * deleted.+	 */+	public enum OsAccountStatus {+		UNKNOWN(0, "Unknown"),+		ACTIVE(1, "Active"),+		DISABLED(2, "Disabled"),+		DELETED(2, "Deleted");++		private final int id;+		private final String name;++		OsAccountStatus(int id, String name) {+			this.id = id;+			this.name = name;+		}++		/**+		 * Get account status id.+		 *+		 * @return Account status id.+		 */+		public int getId() {+			return id;+		}++		/**+		 * Get the account status enum name.+		 *+		 * @return+		 */+		String getName() {

Doesn't this need to be public?

raman-bt

comment created time in 7 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

+/*+ * Sleuth Kit Data Model+ *+ * Copyright 2020-2021 Basis Technology Corp.+ * Contact: carrier <at> sleuthkit <dot> org+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+package org.sleuthkit.datamodel;++import java.util.ArrayList;+import java.util.Collection;+import java.util.Collections;+import java.util.List;+import java.util.Optional;+import java.util.Set;++/**+ * Abstracts an OS user account.+ *+ * An OS user account may own files and (some) artifacts.+ *+ */+public final class OsAccount implements Content {++	final static long NO_USER = -1;+	final static String NULL_UID_STR = null;

I'm not sure what value this provides.

raman-bt

comment created time in 7 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 private void createAccountTables(Statement stmt) throws SQLException { 				+ "FOREIGN KEY(account2_id) REFERENCES accounts(account_id), " 				+ "FOREIGN KEY(relationship_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 				+ "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");+		+		stmt.execute("CREATE TABLE tsk_os_account_realms (id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, "+				+ "name TEXT NOT NULL, "	// realm name - host name or domain name+				+ "unique_id TEXT DEFAULT NULL, "		// a sid/uid or some some other unique identifier, may be null+				+ "host_id " + dbQueryHelper.getBigIntType() + " DEFAULT NULL, " // if the realm just comprises of a single host+				+ "name_type INTEGER, "	// indicates if the realm name was  was expressed or inferred +				+ "UNIQUE(name), "+				+ "FOREIGN KEY(host_id) REFERENCES tsk_hosts(id) )");+		+		stmt.execute("CREATE TABLE tsk_os_accounts (id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, "+				+ "login_name TEXT, "	// login name, if available, may be null+				+ "full_name TEXT, "	// full name, if available, may be null+				+ "realm_id " + dbQueryHelper.getBigIntType() + ", "		// row id for the realm, may be null if only SID is known +				+ "unique_id TEXT, "	// SID/UID, if available

Maybe we want to call this column uid, assuming UID is a domain term?

raman-bt

comment created time in a day

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 private void createAccountTables(Statement stmt) throws SQLException { 				+ "FOREIGN KEY(account2_id) REFERENCES accounts(account_id), " 				+ "FOREIGN KEY(relationship_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 				+ "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");+		+		stmt.execute("CREATE TABLE tsk_os_account_realms (id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, "+				+ "name TEXT NOT NULL, "	// realm name - host name or domain name+				+ "unique_id TEXT DEFAULT NULL, "		// a sid/uid or some some other unique identifier, may be null+				+ "host_id " + dbQueryHelper.getBigIntType() + " DEFAULT NULL, " // if the realm just comprises of a single host+				+ "name_type INTEGER, "	// indicates if the realm name was  was expressed or inferred +				+ "UNIQUE(name), "+				+ "FOREIGN KEY(host_id) REFERENCES tsk_hosts(id) )");+		+		stmt.execute("CREATE TABLE tsk_os_accounts (id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, "+				+ "login_name TEXT, "	// login name, if available, may be null+				+ "full_name TEXT, "	// full name, if available, may be null+				+ "realm_id " + dbQueryHelper.getBigIntType() + ", "		// row id for the realm, may be null if only SID is known +				+ "unique_id TEXT, "	// SID/UID, if available+				+ "signature TEXT NOT NULL, "	// realm/loginname or sid +				+ "status INTEGER, "    // enabled/disabled/deleted+				+ "admin INTEGER DEFAULT 0," // is admin account+				+ "type INTEGER, "	// service/interactive+				+ "creation_date_time " + dbQueryHelper.getBigIntType() + ", "		

How about we stick to domain terms and call this column created_date as in the doc?

raman-bt

comment created time in a day

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 private void createAccountTables(Statement stmt) throws SQLException { 				+ "FOREIGN KEY(account2_id) REFERENCES accounts(account_id), " 				+ "FOREIGN KEY(relationship_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 				+ "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");+		+		stmt.execute("CREATE TABLE tsk_os_account_realms (id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, "+				+ "name TEXT NOT NULL, "	// realm name - host name or domain name+				+ "unique_id TEXT DEFAULT NULL, "		// a sid/uid or some some other unique identifier, may be null+				+ "host_id " + dbQueryHelper.getBigIntType() + " DEFAULT NULL, " // if the realm just comprises of a single host+				+ "name_type INTEGER, "	// indicates if the realm name was  was expressed or inferred +				+ "UNIQUE(name), "+				+ "FOREIGN KEY(host_id) REFERENCES tsk_hosts(id) )");+		+		stmt.execute("CREATE TABLE tsk_os_accounts (id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, "+				+ "login_name TEXT, "	// login name, if available, may be null

Should this be DEFAULT NULL?

raman-bt

comment created time in a day

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

+/*+ * Sleuth Kit Data Model+ *+ * Copyright 2020-2021 Basis Technology Corp.+ * Contact: carrier <at> sleuthkit <dot> org+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+package org.sleuthkit.datamodel;++import java.util.ArrayList;+import java.util.Collection;+import java.util.Collections;+import java.util.List;+import java.util.Optional;+import java.util.Set;++/**+ * Abstracts an OS user account.+ *+ * An OS user account may own files and (some) artifacts.+ *+ */+public final class OsAccount implements Content {++	final static long NO_USER = -1;+	final static String NULL_UID_STR = null;++	private final SleuthkitCase sleuthkitCase;+	+	private final long objId;	+	private final OsAccountRealm realm;		// realm where the username is unique - a domain or a host name, may be null+	private final String loginName;	// user login name - may be null+	private final String uniqueId;	// a unique user sid/uid, may be null+	private final String signature; // something that uniquely identifies this user - either the uniqueId or the realmName/userName.++	private String fullName;	// full name+	private boolean isAdmin = false;	// is admin account.+	private OsAccountType osAccountType = OsAccountType.UNKNOWN;+	private OsAccountStatus osAccountStatus = OsAccountStatus.UNKNOWN;+	private long creationTime = 0;++	private final List<OsAccountAttribute> osAccountAttributes = new ArrayList<>();++	/**+	 * Encapsulates status of an account - whether is it active or disabled or+	 * deleted.+	 */+	public enum OsAccountStatus {+		UNKNOWN(0, "Unknown"),+		ACTIVE(1, "Active"),+		DISABLED(2, "Disabled"),+		DELETED(2, "Deleted");

@bcarrier In the doc, status is listed as: "enabled vs Disabled vs Deleted." Is "Unknown" meaningful here? I see an "Unknown" below in OsAccountType, which makes sense to me. Maybe "Unknown" in this enum is misplaced?

raman-bt

comment created time in 7 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 private void createAccountTables(Statement stmt) throws SQLException { 				+ "FOREIGN KEY(account2_id) REFERENCES accounts(account_id), " 				+ "FOREIGN KEY(relationship_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 				+ "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");+		+		stmt.execute("CREATE TABLE tsk_os_account_realms (id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, "+				+ "name TEXT NOT NULL, "	// realm name - host name or domain name+				+ "unique_id TEXT DEFAULT NULL, "		// a sid/uid or some some other unique identifier, may be null

Maybe we want to call this column uid, assuming UID is a domain term?

raman-bt

comment created time in a day

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

+/*+ * Sleuth Kit Data Model+ *+ * Copyright 2020 Basis Technology Corp.+ * Contact: carrier <at> sleuthkit <dot> org+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *	 http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+package org.sleuthkit.datamodel;+++/**+ * DataArtifact is a category of artifact types that are simply data directly+ * extracted from a data source.+ *+ */+public class DataArtifact extends BlackboardArtifact {+	+	private final OsAccount osAccount;+	+	+	DataArtifact(SleuthkitCase sleuthkitCase, long artifactID, long sourceObjId, long artifactObjId, long dataSourceObjId, int artifactTypeID, String artifactTypeName, String displayName, ReviewStatus reviewStatus, OsAccount osAccount) {+		super(sleuthkitCase, artifactID, sourceObjId, artifactObjId, dataSourceObjId, artifactTypeID, artifactTypeName, displayName, reviewStatus);+		this.osAccount = osAccount;+	}+	+	+	/**+	 * Gets the user for this artifact.+	 *+	 * @return OsAccount+	 *+	 * @throws TskCoreException If there is an error getting the user+	 */+	public OsAccount getOsAccount() throws TskCoreException {+		return osAccount;+	}

@bcarrier Are all DataArtifacts expected to have an associated OS account? I don't believe that we have a tsk_data_artifacts table definition yet.

raman-bt

comment created time in 7 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 private void createAccountTables(Statement stmt) throws SQLException { 				+ "FOREIGN KEY(account2_id) REFERENCES accounts(account_id), " 				+ "FOREIGN KEY(relationship_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 				+ "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");+		+		stmt.execute("CREATE TABLE tsk_os_account_realms (id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, "+				+ "name TEXT NOT NULL, "	// realm name - host name or domain name+				+ "unique_id TEXT DEFAULT NULL, "		// a sid/uid or some some other unique identifier, may be null+				+ "host_id " + dbQueryHelper.getBigIntType() + " DEFAULT NULL, " // if the realm just comprises of a single host+				+ "name_type INTEGER, "	// indicates if the realm name was  was expressed or inferred +				+ "UNIQUE(name), "+				+ "FOREIGN KEY(host_id) REFERENCES tsk_hosts(id) )");+		+		stmt.execute("CREATE TABLE tsk_os_accounts (id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, "+				+ "login_name TEXT, "	// login name, if available, may be null+				+ "full_name TEXT, "	// full name, if available, may be null

Should this be DEFAULT NULL?

raman-bt

comment created time in a day

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 public void save() throws TskCoreException { 		} 	} +	/**+	 * Get the uidStr.+	 * +	 * @return String uid. Returns an empty string if no uid is recorded.+	 */+	public String getUidStr() {+		return Objects.nonNull(uidStr) ? uidStr+				: "";+	}+		+	/**+	 * Get the row id of the owing user. +	 * +	 * @return rowId, or OsAccount.NO_USER+	 */+	public long getUserRowId() {+		return userRowId;+	}+	+	/**+	 * Gets the user for the file.+	 * +	 * @return OsAccount  +	 * +	 * @throws TskCoreException  If there is an error getting the user+	 */+	public OsAccount getUser() throws TskCoreException {+		+		// run a query to get the user row id from the tsk_files+		String queryStr = "SELECT os_account_row_id FROM tsk_files WHERE obj_id = " + this.getId();+		try (SleuthkitCase.CaseDbConnection connection = getSleuthkitCase().getConnection();+				Statement statement = connection.createStatement();+				ResultSet resultSet = connection.executeQuery(statement, queryStr);) {++			if (resultSet.next()) {+					long userRowId = resultSet.getLong("os_account_row_id");+					return getSleuthkitCase().getOsAccountManager().getOsAccount(userRowId);+			} else {+				throw new TskCoreException(String.format("Error getting user account id for file (obj_id = %d)", this.getId()));+			}+			+		} catch (SQLException ex) {+			throw new TskCoreException(String.format("Error getting user account id for file (obj_id = %d)", this.getId()), ex);

This error message only accurately describes one of the operations in the try block.

But I'm not sure why we need two queries here, though. If we are storing the PK from os_accounts in a field in the class, can't we go straight to the OsAccountManager?

raman-bt

comment created time in a day

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

+/*+ * Sleuth Kit Data Model+ *+ * Copyright 2020 Basis Technology Corp.+ * Contact: carrier <at> sleuthkit <dot> org+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *	 http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+package org.sleuthkit.datamodel;+++/**+ * DataArtifact is a category of artifact types that are simply data directly+ * extracted from a data source.+ *+ */+public class DataArtifact extends BlackboardArtifact {

Please make this class final.

raman-bt

comment created time in 7 hours

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 public void save() throws TskCoreException { 		} 	} +	/**+	 * Get the uidStr.+	 * +	 * @return String uid. Returns an empty string if no uid is recorded.+	 */+	public String getUidStr() {+		return Objects.nonNull(uidStr) ? uidStr+				: "";+	}+		+	/**+	 * Get the row id of the owing user. +	 * +	 * @return rowId, or OsAccount.NO_USER+	 */+	public long getUserRowId() {+		return userRowId;+	}+	+	/**+	 * Gets the user for the file.+	 * +	 * @return OsAccount  +	 * +	 * @throws TskCoreException  If there is an error getting the user+	 */+	public OsAccount getUser() throws TskCoreException {

How about getOsAccount(), see previous comments. I think the consistency will help client and maintainer developers.

raman-bt

comment created time in a day

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 public void save() throws TskCoreException { 		} 	} +	/**+	 * Get the uidStr.+	 * +	 * @return String uid. Returns an empty string if no uid is recorded.+	 */+	public String getUidStr() {

I think it would be better to call this method getUid() to make it expressive of the domain rather than the data type. See previous comments.

raman-bt

comment created time in a day

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 			String md5Hash, String sha256Hash, FileKnown knownState, 			String parentPath, 			String mimeType,-			String extension, +			String extension,+			String uidStr,+			long userRowId,

See previous comment about uidStr and userRowId.

raman-bt

comment created time in a day

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 	private final List<Attribute> fileAttributesCache = new ArrayList<Attribute>(); 	private boolean loadedAttributesCacheFromDb = false; +	private final String uidStr;	// SID/uid

I think that we should just call this uid. The Str prefix seems to distract from what it is, a UID, and on the whole, we usually use problem domain terms rather than data types for our field names.

raman-bt

comment created time in a day

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 private void createFileTables(Statement stmt) throws SQLException { 				+ "mtime " + dbQueryHelper.getBigIntType() + ", mode INTEGER, uid INTEGER, gid INTEGER, md5 TEXT, sha256 TEXT, " 				+ "known INTEGER, " 				+ "parent_path TEXT, mime_type TEXT, extension TEXT, "+				+ "uid_str TEXT, "+				+ "os_account_row_id " + dbQueryHelper.getBigIntType() + ", "

How about os_account_row_id => os_account_id. I think that would be more consistent with the way we usually name our FK columns. See previous comments.

raman-bt

comment created time in a day

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 	private final List<Attribute> fileAttributesCache = new ArrayList<Attribute>(); 	private boolean loadedAttributesCacheFromDb = false; +	private final String uidStr;	// SID/uid+	private final long userRowId;

I think that we should call this osAcctId or osAccountId to be consistent with our usual naming conventions. I can't think of any paces where we call out a "row ID." But I don't think we should call it userId here and then expect to pass it to the OsAccountManager, we would be overloading osAccountId/userId in a way that might make the code a bit harder to follow.

raman-bt

comment created time in a day

Pull request review commentsleuthkit/sleuthkit

4039 os user account.

 public void save() throws TskCoreException { 		} 	} +	/**+	 * Get the uidStr.+	 * +	 * @return String uid. Returns an empty string if no uid is recorded.+	 */+	public String getUidStr() {+		return Objects.nonNull(uidStr) ? uidStr+				: "";+	}+		+	/**+	 * Get the row id of the owing user. +	 * +	 * @return rowId, or OsAccount.NO_USER+	 */+	public long getUserRowId() {

Does this need to be a public method?

In any case, I think we should focus on domain terminology rather than programming details. We could name this method something like getUserId or getOsAccountId (see previous comments).

raman-bt

comment created time in a day

push eventalphagov/whitehall

Kevin Dew

commit sha 57ce87ef510a858cc4ec0f4dff1890c0ffbd7148

Make Dockerfile more production focused This removes REDIS_HOST as GOV.UK no longer use that env var to configure Redis. The rest of the Dockerfile is then updated in a consistent manner to static [1], where it's tailored towards production running - reflecting that no-one can use this for test environments (and potentially development ones). [1]: https://github.com/alphagov/static/pull/2327

view details

Andy Sellick

commit sha 3206761d517bc60558a3d85ea8988d0ecf452c12

Use updated component filename - subscription links component was renamed to match component conventions, updating here as well to avoid forthcoming breaking change

view details

Kevin Dew

commit sha 43a83d8c944114a72f4ce5069b195f2530f0a914

Merge pull request #5954 from alphagov/redis-host-dockerfile Make Dockerfile more production focused

view details

Andy Sellick

commit sha 8ea113746eaa85141726ff4e14bf5beb82a7e32c

Merge pull request #5955 from alphagov/fix-component-references Use updated component filename

view details

Peter Hartshorn

commit sha 2669db52389e0210ddfac0537d30aed6c4c12f71

Remove unused statistic announcements code Statistic Announcements are redirected to another app straight from the controller and so all the views, presenters and other supporting code is never called upon and so can be removed.

view details

Peter Hartshorn

commit sha 15d92dbeda988494293f4f9036554f7b081678fa

Remove more unused finder logic Whitehall finders (statisitics, annoucements and publications) now only serve as foreign locale finders as from their controllers they're redirected to Finder Frontend if the users locale is English. This means we can remove a lot of the custom filter logic and the supporting classes that was previously used which simplifys the code.

view details

Peter Hartshorn

commit sha 99a2c2ecdd27f5cc2a8bbc6729cd5ec691601aea

This partial is only used once so removed

view details

Peter Hartshorn

commit sha 5a5e995adadbf581fce0d101425ea073b65295a4

Remove unused FilterHelper

view details

Peter Hartshorn

commit sha ce2ca32251ad19c228f7ed5a7554a0d73ade02fe

Merge pull request #5965 from alphagov/remove-unused-code Remove unused code

view details

push time in 7 hours

more