changeset 9:60c8ab006e55

Update metadata Update password file metadata when saving. Add and update metadata when creating and modifying records.
author Guido Berhoerster <guido+pwm@berhoerster.name>
date Fri, 28 Jul 2017 09:53:46 +0200
parents 25e227eba3da
children 17fb30016e64
files pwfile.c util.h
diffstat 2 files changed, 124 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/pwfile.c	Fri Jul 28 08:20:38 2017 +0200
+++ b/pwfile.c	Fri Jul 28 09:53:46 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Guido Berhoerster <guido+pwm@berhoerster.name>
+ * Copyright (C) 2017 Guido Berhoerster <guido+pwm@berhoerster.name>
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -33,7 +33,9 @@
 #ifdef	HAVE_SYS_TREE_H
 #include <sys/tree.h>
 #endif
+#include <sys/utsname.h>
 #include <unistd.h>
+#include <time.h>
 
 #include "pwfile.h"
 #include "util.h"
@@ -301,6 +303,81 @@
 	return (retval);
 }
 
+static void
+update_file_metadata(struct pws3_file *file)
+{
+	struct pws3_field *save_app_field;
+	struct pws3_field *save_timestamp_field;
+	char		*logname;
+	const char	default_username[] = "unknown user";
+	const char	*username;
+	size_t		username_len;
+	struct utsname	utsn;
+	const char	default_hostname[] = "unknown host";
+	const char	*hostname;
+	char		user_host[1024];
+	struct pws3_field *save_user_host_field;
+	struct pws3_field *save_user_field;
+	struct pws3_field *save_host_field;
+
+	save_app_field =
+	    pws3_field_create(1, PWS3_HEADER_FIELD_SAVE_APPLICATION);
+	if (save_app_field == NULL) {
+		err(1, "pws3_field_create");
+	}
+	if (pws3_field_set_text(save_app_field, PACKAGE " V" VERSION) !=
+	    0) {
+		err(1, "pws3_field_set_text");
+	}
+	pws3_file_set_header_field(file, save_app_field);
+
+	save_timestamp_field =
+	    pws3_field_create(1, PWS3_HEADER_FIELD_SAVE_TIMESTAMP);
+	if (save_timestamp_field == NULL) {
+		err(1, "pws3_field_create");
+	}
+	pws3_field_set_time(save_timestamp_field, time(NULL));
+	pws3_file_set_header_field(file, save_timestamp_field);
+
+	logname = getenv("LOGNAME");
+	if (logname == NULL) {
+		logname = getlogin();
+	}
+	username = (logname != NULL) ? logname : default_username;
+	username_len = MIN(strlen(username), sizeof (user_host) - 4 - 1);
+	hostname = (uname(&utsn) == 0) ? utsn.nodename : default_hostname;
+	snprintf(user_host, sizeof (user_host), "%04zx%s%s", username_len,
+	    username, hostname);
+
+	save_user_host_field =
+	    pws3_field_create(1, PWS3_HEADER_FIELD_SAVE_USER_HOST);
+	if (save_user_host_field == NULL) {
+		err(1, "pws3_field_create");
+	}
+	if (pws3_field_set_text(save_user_host_field, user_host) != 0) {
+		err(1, "pws3_field_set_text");
+	}
+	pws3_file_set_header_field(file, save_user_host_field);
+
+	save_user_field = pws3_field_create(1, PWS3_HEADER_FIELD_SAVE_USER);
+	if (save_user_field == NULL) {
+		err(1, "pws3_field_create");
+	}
+	if (pws3_field_set_text(save_user_field, logname) != 0) {
+		err(1, "pws3_field_set_text");
+	}
+	pws3_file_set_header_field(file, save_user_field);
+
+	save_host_field = pws3_field_create(1, PWS3_HEADER_FIELD_SAVE_HOST);
+	if (save_host_field == NULL) {
+		err(1, "pws3_field_create");
+	}
+	if (pws3_field_set_text(save_host_field, hostname) != 0) {
+		err(1, "pws3_field_set_text");
+	}
+	pws3_file_set_header_field(file, save_host_field);
+}
+
 int
 pwfile_write_file(struct pwm_ctx *ctx)
 {
@@ -310,6 +387,10 @@
 	int	fd = -1;
 	FILE	*fp = NULL;
 
+	/* update password file metadata */
+	update_file_metadata(ctx->file);
+
+	/* make a backup copy of the existing password file */
 	if (make_backup_copy(ctx->filename) != 0) {
 		goto out;
 	}
@@ -519,17 +600,42 @@
 static void
 update_record(struct pws3_record *pws3_record, struct record *record)
 {
+	time_t		now;
+	struct pws3_field *ctime_field;
+	struct pws3_field *mtime_field;
 	struct pws3_field *title_field;
 	struct pws3_field *group_field;
 	struct pws3_field *username_field;
 	struct pws3_field *password_field;
+	struct pws3_field *password_mtime_field;
 	struct pws3_field *notes_field;
 	struct pws3_field *url_field;
 
+	now = time(NULL);
+
+	ctime_field = pws3_record_get_field(pws3_record,
+	    PWS3_RECORD_FIELD_CREATION_TIME);
+	if (ctime_field == NULL) {
+		ctime_field = pws3_field_create(0,
+		    PWS3_RECORD_FIELD_CREATION_TIME);
+		if (ctime_field == NULL) {
+			err(1, "pws3_field_create");
+		}
+		pws3_field_set_time(ctime_field, now);
+		pws3_record_set_field(pws3_record, ctime_field);
+	}
+
+	mtime_field = pws3_field_create(0, PWS3_RECORD_FIELD_MODIFICATION_TIME);
+	if (mtime_field == NULL) {
+		err(1, "pws3_field_create");
+	}
+	pws3_field_set_time(mtime_field, now);
+	pws3_record_set_field(pws3_record, mtime_field);
+
 	if (record->title != NULL) {
 		title_field = pws3_field_create(0, PWS3_RECORD_FIELD_TITLE);
 		if (title_field == NULL) {
-			err(1, "pws3_record_field_create");
+			err(1, "pws3_field_create");
 		}
 		if (pws3_field_set_text(title_field,
 		    record->title) != 0) {
@@ -540,7 +646,7 @@
 	if (record->group != NULL) {
 		group_field = pws3_field_create(0, PWS3_RECORD_FIELD_GROUP);
 		if (group_field == NULL) {
-			err(1, "pws3_record_field_create");
+			err(1, "pws3_field_create");
 		}
 		if (pws3_field_set_text(group_field,
 		    record->group) != 0) {
@@ -552,7 +658,7 @@
 		username_field = pws3_field_create(0,
 		    PWS3_RECORD_FIELD_USERNAME);
 		if (username_field == NULL) {
-			err(1, "pws3_record_field_create");
+			err(1, "pws3_field_create");
 		}
 		if (pws3_field_set_text(username_field,
 		    record->username) != 0) {
@@ -564,18 +670,26 @@
 		password_field = pws3_field_create(0,
 		    PWS3_RECORD_FIELD_PASSWORD);
 		if (password_field == NULL) {
-			err(1, "pws3_record_field_create");
+			err(1, "pws3_field_create");
 		}
 		if (pws3_field_set_text(password_field,
 		    record->password) != 0) {
 			err(1, "pws3_field_set_text");
 		}
 		pws3_record_set_field(pws3_record, password_field);
+
+		password_mtime_field = pws3_field_create(0,
+		    PWS3_RECORD_FIELD_PASSWORD_MODIFICATION_TIME);
+		if (password_mtime_field == NULL) {
+			err(1, "pws3_field_create");
+		}
+		pws3_field_set_time(password_mtime_field, now);
+		pws3_record_set_field(pws3_record, password_mtime_field);
 	}
 	if (record->notes != NULL) {
 		notes_field = pws3_field_create(0, PWS3_RECORD_FIELD_NOTES);
 		if (notes_field == NULL) {
-			err(1, "pws3_record_field_create");
+			err(1, "pws3_field_create");
 		}
 		if (pws3_field_set_text(notes_field, record->notes) != 0) {
 			err(1, "pws3_field_set_text");
@@ -585,7 +699,7 @@
 	if (record->url != NULL) {
 		url_field = pws3_field_create(0, PWS3_RECORD_FIELD_URL);
 		if (url_field == NULL) {
-			err(1, "pws3_record_field_create");
+			err(1, "pws3_field_create");
 		}
 		if (pws3_field_set_text(url_field, record->url) != 0) {
 			err(1, "pws3_field_set_text");
--- a/util.h	Fri Jul 28 08:20:38 2017 +0200
+++ b/util.h	Fri Jul 28 09:53:46 2017 +0200
@@ -32,6 +32,9 @@
 #define	COUNTOF(x)	((sizeof (x)/sizeof (0[x])) / ((size_t)(!(sizeof (x) % \
     sizeof (0[x])))))
 
+#define	MAX(x, y)	(((x) > (y)) ? (x) : (y))
+#define	MIN(x, y)	(((x) < (y)) ? (x) : (y))
+
 void *	xmalloc(size_t);
 void *	xrealloc(void *, size_t);
 char *	xstrdup(const char *);