1 /*
2 * Copyright (C) 2019-2020 Niko Rosvall <niko@byteptr.com>
3 */
4
5 #define _XOPEN_SOURCE 700
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <stdbool.h>
10 #include <string.h>
11 #include <sys/stat.h>
12 #include "entry.h"
13 #include "utils.h"
14 #include "crypto.h"
15 #include "qr.h"
16
17 /* Function returns NULL if the environment variable
18 YLVA_DEFAULT_USERNAME is not set.
19 */
get_default_username()20 char* get_default_username()
21 {
22 char* username = getenv("YLVA_DEFAULT_USERNAME");
23 return username;
24 }
25
get_output_color()26 static char *get_output_color()
27 {
28 char *color = getenv("YLVA_COLOR");
29
30 if(color == NULL)
31 return COLOR_DEFAULT;
32
33 if(strcmp(color, "BLUE") == 0)
34 return "\x1B[34m";
35 else if(strcmp(color, "RED") == 0)
36 return "\x1B[31m";
37 else if(strcmp(color, "GREEN") == 0)
38 return "\x1B[32m";
39 else if(strcmp(color, "YELLOW") == 0)
40 return "\x1B[33m";
41 else if(strcmp(color, "MAGENTA") == 0)
42 return "\x1B[35m";
43 else if(strcmp(color, "CYAN") == 0)
44 return "\x1B[36m";
45 else if(strcmp(color, "WHITE") == 0)
46 return "\x1B[37m";
47 else
48 return COLOR_DEFAULT; /* Handle empty variable too */
49 }
50
print_entry(Entry_t * entry,int show_password,int as_qrcode)51 bool print_entry(Entry_t *entry, int show_password, int as_qrcode)
52 {
53 char *color = get_output_color();
54
55 fprintf(stdout, "=====================================================================\n");
56
57 if(as_qrcode == 1) {
58 print_entry_as_qr(entry);
59 }
60 else {
61 /* Set the color */
62 fprintf(stdout, "%s", color);
63
64 fprintf(stdout, "ID: %d\n", entry->id);
65 fprintf(stdout, "Title: %s\n", entry->title);
66 fprintf(stdout, "User: %s\n", entry->user);
67 fprintf(stdout, "Url: %s\n", entry->url);
68
69 if(show_password == 1)
70 fprintf(stdout, "Password: %s\n", entry->password);
71 else
72 fprintf(stdout, "Password: **********\n");
73
74 fprintf(stdout, "Notes: %s\n", entry->notes);
75 fprintf(stdout, "Modified: %s\n", entry->stamp);
76
77 /* Reset the color */
78 fprintf(stdout, "%s", COLOR_DEFAULT);
79 }
80
81 fprintf(stdout, "=====================================================================\n");
82
83 return 0;
84 }
85
file_exists(const char * path)86 bool file_exists(const char *path)
87 {
88 struct stat buf;
89
90 if(stat(path, &buf) != 0)
91 return false;
92
93 return true;
94 }
95
96 /* Function checks that we have a valid path
97 * in our ylva.open_db file and if the database is not
98 * encrypted.
99 */
has_active_database()100 bool has_active_database()
101 {
102 char *path = NULL;
103
104 path = get_open_db_path_holder_filepath();
105
106 if(!path)
107 return false;
108
109 struct stat buf;
110
111 if(stat(path, &buf) != 0)
112 {
113 free(path);
114 return false;
115 }
116
117 //If the database is encrypted, it's not active so return false
118 if(is_file_encrypted(path))
119 {
120 free(path);
121 return false;
122 }
123
124 free(path);
125
126 return true;
127 }
128
129 /* Returns the path of ~/.ylva.open_db file.
130 * Caller must free the return value */
get_open_db_path_holder_filepath()131 char *get_open_db_path_holder_filepath()
132 {
133 char *home = NULL;
134 char *path = NULL;
135
136 home = getenv("HOME");
137
138 if(!home)
139 return NULL;
140
141 /* /home/user/.ylva.open_db */
142 path = tmalloc(sizeof(char) * (strlen(home) + 15));
143
144 strcpy(path, home);
145 strcat(path, "/.ylva.open_db");
146
147 return path;
148 }
149
150 /* Reads and returns the path of currently decrypted
151 * database. Caller must free the return value */
read_active_database_path()152 char *read_active_database_path()
153 {
154 FILE *fp = NULL;
155 char *path = NULL;
156 char *opendbholderpath = NULL;
157 size_t len;
158
159 path = get_open_db_path_holder_filepath();
160
161 if(!path)
162 return NULL;
163
164 fp = fopen(path, "r");
165
166 if(!fp)
167 {
168 free(path);
169 return NULL;
170 }
171
172 /* We only need the first line from the file */
173
174 if(getline(&opendbholderpath, &len, fp) < 0)
175 {
176 if(opendbholderpath)
177 free(opendbholderpath);
178
179 fclose(fp);
180 free(path);
181
182 return NULL;
183 }
184
185 fclose(fp);
186 free(path);
187
188 return opendbholderpath;
189 }
190
write_active_database_path(const char * db_path)191 void write_active_database_path(const char *db_path)
192 {
193 FILE *fp = NULL;
194 char *path = NULL;
195
196 path = get_open_db_path_holder_filepath();
197
198 if(!path)
199 return;
200
201 fp = fopen(path, "w");
202
203 if(!fp)
204 {
205 fprintf(stderr, "Error creating ~/.ylva.open_db file\n");
206 free(path);
207 return;
208 }
209
210 fprintf(fp, "%s", db_path);
211 fclose(fp);
212
213 free(path);
214 }
215
216 //Simple malloc wrapper to prevent enormous error
217 //checking every where in the code
tmalloc(size_t size)218 void *tmalloc(size_t size)
219 {
220 void *data = NULL;
221
222 data = malloc(size);
223
224 if(data == NULL)
225 {
226 fprintf(stderr, "Malloc failed. Abort.\n");
227 abort();
228 }
229
230 return data;
231 }
232
set_file_owner_rw(const char * path)233 void set_file_owner_rw(const char *path)
234 {
235 if(chmod(path, S_IRUSR | S_IWUSR) != 0)
236 fprintf(stderr, "WARNING: Error changing permissions of file %s\n", path);
237 }
238