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