List of commits:
Subject Hash Author Date (UTC)
Added password support df6d270a3e243084069a31fe980d76c97d89a861 Catalin(ux) M. BOIE 2018-02-13 22:46:53
Checkpoint 049e12584744b8a51bfc5867fd0e7b2db0592deb Catalin(ux) M. BOIE 2018-02-11 22:25:13
Fixed a bug in totp, added keys in memory abec61861e2f37398026dbe7342d7751390e95d8 Catalin(ux) M. BOIE 2018-02-04 18:36:12
Initial version c641fafbd46342cd24fde45129cc3637b7ca65bc Catalin(ux) M. BOIE 2018-02-03 23:42:32
Commit df6d270a3e243084069a31fe980d76c97d89a861 - Added password support
Author: Catalin(ux) M. BOIE
Author date (UTC): 2018-02-13 22:46
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2018-02-13 22:46
Parent(s): 049e12584744b8a51bfc5867fd0e7b2db0592deb
Signing key:
Tree: 267bf3e28a01ad641454d3d737ef929dabd1a9f6
File Lines added Lines deleted
Makefile.in 5 2
TODO 5 5
conf.c 8 3
conf.h 1 1
key.c 55 2
key.h 8 2
nf2fa.conf.sample 6 2
nf2fa.service 12 0
nf2fa.spec.in 2 0
nf2fac.c 36 13
nf2fad.c 112 67
protocol.c 23 6
protocol.h 2 2
util.c 48 0
util.h 2 0
File Makefile.in changed (mode: 100644) (index fdade10..cabb751)
... ... util.o: util.c util.h $(DEP)
14 14 totp.o: totp.c totp.h $(DEP) totp.o: totp.c totp.h $(DEP)
15 15 gcc $(CFLAGS) totp.c -c gcc $(CFLAGS) totp.c -c
16 16
17 key.o: key.c key.h $(DEP)
17 key.o: key.c key.h conf.h $(DEP)
18 18 gcc $(CFLAGS) key.c -c gcc $(CFLAGS) key.c -c
19 19
20 20 protocol.o: protocol.c protocol.h $(DEP) protocol.o: protocol.c protocol.h $(DEP)
 
... ... brute.o: brute.c brute.h $(DEP)
29 29 nf2fad: nf2fad.c $(OBJS) totp.h key.h protocol.h util.h conf.h brute.h $(DEP) nf2fad: nf2fad.c $(OBJS) totp.h key.h protocol.h util.h conf.h brute.h $(DEP)
30 30 gcc $(CFLAGS) nf2fad.c -o nf2fad $(OBJS) $(LIBS) gcc $(CFLAGS) nf2fad.c -o nf2fad $(OBJS) $(LIBS)
31 31
32 nf2fac: nf2fac.c $(OBJS) totp.h key.h protocol.h util.h $(DEP)
32 nf2fac: nf2fac.c $(OBJS) totp.h key.h protocol.h util.h conf.h $(DEP)
33 33 gcc $(CFLAGS) nf2fac.c -o nf2fac $(OBJS) $(LIBS) gcc $(CFLAGS) nf2fac.c -o nf2fac $(OBJS) $(LIBS)
34 34
35 35 .PHONY: clean .PHONY: clean
 
... ... install: all
46 46 @cp -vd nf2fad $(I_USR_SBIN) @cp -vd nf2fad $(I_USR_SBIN)
47 47 @mkdir -p $(I_USR_BIN) @mkdir -p $(I_USR_BIN)
48 48 @cp -vd nf2fac $(I_USR_BIN) @cp -vd nf2fac $(I_USR_BIN)
49 @mkdir -p $(I_ETC)
50 @cp -vd --no-clobber nf2fa.conf.sample $(I_ETC)/nf2fa.conf
51 @cp -vd nf2fa.conf.sample $(I_ETC)/
File TODO changed (mode: 100644) (index 96fb1fd..c83b584)
1 1 [ ] Warn user that nf2fa is not for allowing non authenticated connections. [ ] Warn user that nf2fa is not for allowing non authenticated connections.
2 2 [ ] Document commands. [ ] Document commands.
3 [ ] Test brute force.
4 3 [ ] Document what rules have to be added in firewall (also for shorewall). [ ] Document what rules have to be added in firewall (also for shorewall).
4 [ ] Test non-root user enroll.
5 [ ] Securely compare strings
5 6 [ ] [ ]
6 7
7 8 == Future == == Future ==
9 [ ] In conf file, limit which users are allowed to do the enroll.
8 10 [ ] Dynamic allocate my_ips, size in conf. [ ] Dynamic allocate my_ips, size in conf.
9 11 [ ] move load_keys to keys.c? [ ] move load_keys to keys.c?
10 12 [ ] Clean keys from memory! No possible, but use an XOR? [ ] Clean keys from memory! No possible, but use an XOR?
11 [ ] Allow (in conf) to select what string is needed for unlock (pin, uid,
12 key_id etc.)
13 13 [ ] Should we also generate scratch codes? [ ] Should we also generate scratch codes?
14 [ ] Add possibility for admin to change the configuration using nf2fac, but
15 testing for uid 0.
16 14 [ ] Save the bad_entries/my_ips tables on disk? [ ] Save the bad_entries/my_ips tables on disk?
17 15 [ ] conf: log file = syslog => syslog [ ] conf: log file = syslog => syslog
18 16 [ ] Command to open the firewall till close command received? [ ] Command to open the firewall till close command received?
19 17 [ ] When we give 'close' command, remove all IPs associated with that uid? [ ] When we give 'close' command, remove all IPs associated with that uid?
20 18 Separate command! Separate command!
19 [ ] Open a port with a minimal web server to be able to unlock the firewall
20 from a web browser (think Windows (missing pattern in icmp) and phones).
21 21 [ ] [ ]
File conf.c changed (mode: 100644) (index c85ca00..f4001b0)
... ... unsigned short queue = 4444;
15 15 unsigned int bad_entries = 4096; unsigned int bad_entries = 4096;
16 16 char *sock_path = "/etc/nf2fa.sock"; char *sock_path = "/etc/nf2fa.sock";
17 17 unsigned int grant_time = 3600; unsigned int grant_time = 3600;
18 unsigned char min_pass_len = 0;
18 19
19 20 /* /*
20 21 * Log configuration options * Log configuration options
 
... ... static void log_conf(void)
25 26 xlog("bad entries: %u\n", bad_entries); xlog("bad entries: %u\n", bad_entries);
26 27 xlog("sock: %s\n", sock_path); xlog("sock: %s\n", sock_path);
27 28 xlog("grant time: %u\n", grant_time); xlog("grant time: %u\n", grant_time);
29 xlog("min pass len: %u\n", min_pass_len);
28 30 } }
29 31
30 32 /* /*
 
... ... int conf_load(const char *file)
38 40 struct stat s; struct stat s;
39 41
40 42 r = stat(file, &s); r = stat(file, &s);
41 if (r == -1) {
42 log_conf();
43 if (r == -1)
43 44 return 0; return 0;
44 }
45 45
46 46 f = fopen(file, "r"); f = fopen(file, "r");
47 47 if (!f) { if (!f) {
 
... ... int conf_load(const char *file)
114 114 continue; continue;
115 115 } }
116 116
117 if (strcmp(buf, "min pass len") == 0) {
118 min_pass_len = strtoul(val, NULL, 0);
119 continue;
120 }
121
117 122 xerr("Invalid conf option: %s\n", buf); xerr("Invalid conf option: %s\n", buf);
118 123 } }
119 124 fclose(f); fclose(f);
File conf.h changed (mode: 100644) (index 43e871c..899ae03)
... ... extern unsigned short queue;
4 4 extern unsigned int bad_entries; extern unsigned int bad_entries;
5 5 extern char *sock_path; extern char *sock_path;
6 6 extern unsigned int grant_time; extern unsigned int grant_time;
7
7 extern unsigned char min_pass_len;
8 8
9 9 int conf_load(const char *file); int conf_load(const char *file);
10 10
File key.c changed (mode: 100644) (index 151c3c5..c48fe04)
9 9 #include <sys/types.h> #include <sys/types.h>
10 10 #include <sys/stat.h> #include <sys/stat.h>
11 11 #include <sys/time.h> #include <sys/time.h>
12 #include <ctype.h>
12 13
14 #include "conf.h"
13 15 #include "key.h" #include "key.h"
14 16
15 17 static char error[256]; static char error[256];
 
... ... char *key_error(void)
19 21 return error; return error;
20 22 } }
21 23
24 /*
25 * Validates the password
26 */
27 int key_pass_validate(const char *pass, const char *pass2)
28 {
29 unsigned char len, i;
30
31 if (strcmp(pass, pass2) != 0) {
32 snprintf(error, sizeof(error),
33 "passwords do not match");
34 return -1;
35 }
36
37 len = strlen(pass);
38
39 if (len % 2 != 0) {
40 snprintf(error, sizeof(error),
41 "password must have an even"
42 " number of characters");
43 return -1;
44 }
45
46 if (len < min_pass_len) {
47 snprintf(error, sizeof(error),
48 "password too short (minimum %hhu)",
49 min_pass_len);
50 return -1;
51 }
52
53 for (i = 0; i < len; i++) {
54 unsigned char c;
55
56 c = toupper(pass[i]);
57 if ((c <= '0') || (c > 'F'))
58 break;
59 }
60 if (i < len) {
61 snprintf(error, sizeof(error),
62 "invalid chars found (0x%02hhx)", pass[i]);
63 return -1;
64 }
65
66 return 0;
67 }
68
22 69 /* /*
23 70 * Save a key to file * Save a key to file
24 71 * Returns -1 on error * Returns -1 on error
 
... ... int key_save(const unsigned int uid, const struct key *k)
50 97
51 98 gettimeofday(&now, NULL); gettimeofday(&now, NULL);
52 99
53 snprintf(buf, sizeof(buf), "%s\n%s\n%ld\n%s\n%ld\n",
54 k->name, k->key, k->ts, k->ip, k->itime);
100 snprintf(buf, sizeof(buf), "%s\n%s\n%ld\n%s\n%ld\n%s\n",
101 k->name, k->key, k->ts, k->ip, k->itime, k->pass);
55 102
56 103 len = strlen(buf); len = strlen(buf);
57 104 n = write(fd, buf, len); n = write(fd, buf, len);
 
... ... int key_save(const unsigned int uid, const struct key *k)
106 153 * ts\n * ts\n
107 154 * ip\n * ip\n
108 155 * itime\n * itime\n
156 * pass\n
109 157 * Returns -1 on error. * Returns -1 on error.
110 158 */ */
111 159 int key_load(struct key *k, const unsigned int uid, const unsigned char key_id) int key_load(struct key *k, const unsigned int uid, const unsigned char key_id)
 
... ... int key_load(struct key *k, const unsigned int uid, const unsigned char key_id)
168 216 sts[i] = '\0'; sts[i] = '\0';
169 217 k->itime = strtol(sts, NULL, 10); pos++; k->itime = strtol(sts, NULL, 10); pos++;
170 218
219 i = 0;
220 while ((pos < n) && (buf[pos] != '\n'))
221 k->pass[i++] = buf[pos++];
222 k->pass[i] = '\0'; pos++;
223
171 224 k->id = key_id; k->id = key_id;
172 225 ret = 0; ret = 0;
173 226 break; break;
File key.h changed (mode: 100644) (index 4642b72..556d515)
... ... struct key
8 8 char key[32]; char key[32];
9 9 unsigned char id; unsigned char id;
10 10 char ip[40]; char ip[40];
11 unsigned char pad[7];
11 char pass[15];
12 12
13 13 struct key *next; struct key *next;
14 14 }; };
15 15
16 16
17 17 char *key_error(void); char *key_error(void);
18
19 int key_pass_validate(const char *pass, const char *pass2);
20 int key_pass_set(struct key *k, const char *pass);
21 int key_pass_verify(struct key *k, const char *pass);
22
18 23 int key_save(const unsigned int uid, const struct key *k); int key_save(const unsigned int uid, const struct key *k);
19 24 int key_load(struct key *k, const unsigned int uid, int key_load(struct key *k, const unsigned int uid,
20 25 const unsigned char key_id); const unsigned char key_id);
21 26
22 int key_remove(const unsigned int uid, const unsigned char id);
27 int key_remove(const unsigned int uid, const unsigned char id);
28
File nf2fa.conf.sample changed (mode: 100644) (index 9ee569e..698b145)
8 8 # Default: 4444 # Default: 4444
9 9 #queue = 0x4444 #queue = 0x4444
10 10 #queue = 65000 #queue = 65000
11 queue = 4444
12 11
13 12 # Number of bad entries slots. # Number of bad entries slots.
14 13 # This is used to prevent brute force attacks. # This is used to prevent brute force attacks.
 
... ... queue = 4444
22 21
23 22 # How much time to grant access, in seconds # How much time to grant access, in seconds
24 23 # Default: 3600 # Default: 3600
25 #grant time = 3600
24 #grant time = 3600
25
26 # Minimum password length, can be 0 = without password.
27 # It must be an even number
28 # Default: 0
29 #min pass len = 10
File nf2fa.service added (mode: 100644) (index 0000000..18063e8)
1 [Unit]
2 Description=nf2fa daemon
3 After=network.target
4
5 [Service]
6 ExecStart=/usr/sbin/nf2fad
7 KillSignal=9
8 Restart=on-failure
9 RestartSec=5s
10
11 [Install]
12 WantedBy=multi-user.target
File nf2fa.spec.in changed (mode: 100644) (index b31805f..b238bd8)
... ... rm -rf ${RPM_BUILD_ROOT}
35 35 %attr (-,root,root) %attr (-,root,root)
36 36 %{_sbindir}/nf2fad %{_sbindir}/nf2fad
37 37 %{_bindir}/nf2fac %{_bindir}/nf2fac
38 %{_sysconfdir}/nf2fac.conf.sample
39 %config(noreplace) @ETC@/nf2fa.conf
38 40 %doc README Changelog %doc README Changelog
39 41
40 42 %changelog %changelog
File nf2fac.c changed (mode: 100644) (index b070c4f..e6d69e1)
18 18
19 19 #include "nf2fa_common.h" #include "nf2fa_common.h"
20 20 #include "util.h" #include "util.h"
21 #include "conf.h"
21 22 #include "totp.h" #include "totp.h"
22 23 #include "key.h" #include "key.h"
23 24 #include "protocol.h" #include "protocol.h"
24 25
25 static char *sock_path = "/etc/nf2fa.sock";
26
27 26 static void help(void) static void help(void)
28 27 { {
29 printf("Usage: nf2afc <command> [options]\n");
30 printf("Commands:\n");
31 printf("\tenroll <name> - enroll new device(s)\n");
32 printf("\tlist - list the enrollments\n");
33 printf("\tunenroll <id> - unenroll a device\n");
28 fprintf(stderr, "Usage: nf2afc <command> [options]\n");
29 fprintf(stderr, "Commands:\n");
30 fprintf(stderr, "\tenroll <name> - enroll new device(s)\n");
31 fprintf(stderr, "\tlist - list the enrollments\n");
32 fprintf(stderr, "\tunenroll <id> - unenroll a device\n");
34 33 } }
35 34
36 35 int main(int argc, char *argv[]) int main(int argc, char *argv[])
37 36 { {
38 37 unsigned char buf[8 * 4096]; unsigned char buf[8 * 4096];
39 int sock;
38 int sock, r;
40 39 struct sockaddr_un sa_un; struct sockaddr_un sa_un;
41 40 socklen_t slen; socklen_t slen;
42 41 ssize_t n; ssize_t n;
43 42 unsigned short i; unsigned short i;
44 43 unsigned char cmd, err; unsigned char cmd, err;
45 44 struct key k; struct key k;
46 char *s;
47 45
48 46 if (argc < 2) { if (argc < 2) {
49 47 help(); help();
50 48 return 1; return 1;
51 49 } }
52 50
53 s = getenv("NF2FA_SOCK");
54 if (s)
55 sock_path = s;
51 r = conf_load(CONF_FILE);
52 if (r == -1) {
53 fprintf(stderr, "Cannot load conf file!\n");
54 return 1;
55 }
56 56
57 57 i = 0; i = 0;
58 58 if (strcmp(argv[1], "enroll") == 0) { if (strcmp(argv[1], "enroll") == 0) {
 
... ... int main(int argc, char *argv[])
63 63
64 64 snprintf(k.name, sizeof(k.name), "%s", argv[2]); snprintf(k.name, sizeof(k.name), "%s", argv[2]);
65 65
66 while (1) {
67 char pass2[15];
68
69 r = read_password("Password (only 0-9 and a-f): ",
70 k.pass, sizeof(k.pass));
71 if (r == -1)
72 return 1;
73
74 r = read_password("Password (confirmation): ",
75 pass2, sizeof(pass2));
76 if (r == -1)
77 return 1;
78
79 r = key_pass_validate(k.pass, pass2);
80 if (r == -1) {
81 fprintf(stderr, "Error: %s\n", key_error());
82 continue;
83 }
84
85 break;
86 }
87
66 88 buf[i++] = NF2FA_CMD_ENROLL; buf[i++] = NF2FA_CMD_ENROLL;
67 89 i += protocol_enqueue_string(buf + i, k.name); i += protocol_enqueue_string(buf + i, k.name);
90 i += protocol_enqueue_string(buf + i, k.pass);
68 91 } else if (strcmp(argv[1], "list") == 0) { } else if (strcmp(argv[1], "list") == 0) {
69 92 buf[i++] = NF2FA_CMD_LIST; buf[i++] = NF2FA_CMD_LIST;
70 93 } else if (strcmp(argv[1], "unenroll") == 0) { } else if (strcmp(argv[1], "unenroll") == 0) {
 
... ... int main(int argc, char *argv[])
195 218 return 0; return 0;
196 219 } }
197 220
198 printf("No Enroll time Name\n");
221 printf("No Enroll time Name\n");
199 222 while (1) { while (1) {
200 223 struct key k; struct key k;
201 224 unsigned int x; unsigned int x;
File nf2fad.c changed (mode: 100644) (index ca35560..cf7745b)
... ... static int send_verdict(const int queue_num, const uint32_t id,
114 114 static int test_2fa(const unsigned char *data, const unsigned int data_len, static int test_2fa(const unsigned char *data, const unsigned int data_len,
115 115 const unsigned int now, const char *ip) const unsigned int now, const char *ip)
116 116 { {
117 unsigned short i, j, last_tested;
117 unsigned short i, j, start, last_check = 0xFFFF;
118 118 unsigned int now30; unsigned int now30;
119 unsigned char c, cmd;
119 unsigned char cmd;
120 120 struct user *q; struct user *q;
121 121 struct key *k; struct key *k;
122 122 char pin[7]; char pin[7];
123 123 int r; int r;
124 124
125 now30 = now / 30;
126
127 125 xlog("DEBUG: %s: %s\n", __func__, ip); xlog("DEBUG: %s: %s\n", __func__, ip);
128 126 dump(data, data_len); dump(data, data_len);
129 127
130 last_tested = 0xFFFF;
131 for (i = 0; i < data_len - (5 - 1); i++) {
132 if (data[i] != 0xAA)
133 continue;
128 // Find first 0xAA
129 start = 0;
130 while ((start < data_len) && (data[start] != 0xaa))
131 start++;
134 132
135 // We do not want to check all clones
136 if ((last_tested != 0xFFFF) && (memcmp(data + last_tested, data + i, 3) == 0))
137 continue;
133 now30 = now / 30;
138 134
139 for (j = 0; j < 3; j++) {
140 c = data[i + 1 + j];
141 if (((c & 0xF) > 9) || ((c >> 4) > 9))
142 break;
143 }
144 if (j != 3) // not found
145 continue;
135 q = users_head;
136 while (q) {
137 k = q->head;
138 while (k) {
139 unsigned char pass_len, needed;
146 140
147 last_tested = i;
148 snprintf(pin, sizeof(pin), "%02hhx%02hhx%02hhx",
149 data[i + 1], data[i + 2], data[i + 3]);
150 cmd = data[i + 4];
151 xlog("DEBUG: Packet pin: %s cmd=0x%02hhx\n", pin, cmd);
141 xlog("DEBUG: uid %u key %03hhu pass=%s\n",
142 q->uid, k->id, k->pass);
152 143
153 if (cmd == 0x11) { // 0x11 = open
154 // do nothing
155 } else if (cmd == 0xcc) { // 0xcc = close
156 // do nothing
157 } else {
158 continue; // invalid command, search again
159 }
144 pass_len = strlen(k->pass) / 2;
145 needed = 1 + pass_len + 3 + 1; // 0xaa + pass + pin + cmd
146
147 i = start;
148 while (1) {
149 char pass[15];
150 unsigned short off;
151
152 if (i + needed > data_len) {
153 xlog("\tDEBUG: too little data: i(%u) + needed(%hhu) > data_len(%hu)\n",
154 i, needed, data_len);
155 break;
156 }
157
158 if (data[i] != 0xaa) {
159 i++;
160 continue;
161 }
162
163 xlog("\tDEBUG: i=%hu 0x%02hhx\n", i, data[i]);
164
165 // Optimization
166 if ((last_check != 0xFFFF)
167 && (memcmp(data + last_check, data + i, needed) == 0)) {
168 //xlog("\tDEBUG: same string\n");
169 i += needed;
170 continue;
171 }
172 last_check = i;
173
174 off = i + 1; // skip 0xaa
175
176 // Check if password is correct
177 for (j = 0; j < pass_len; j++)
178 sprintf(pass + j * 2, "%02x", data[off + j]);
179 off += pass_len;
180
181 if (strcasecmp(k->pass, pass) != 0) {
182 xlog("\tDEBUG: passwords do not match [%s] != [%s]\n", k->pass, pass);
183 i++;
184 continue;
185 }
186 xlog("\tDEBUG: passwords match!\n");
187
188 // Check pin
189 snprintf(pin, sizeof(pin), "%02hhx%02hhx%02hhx",
190 data[off], data[off + 1], data[off + 2]);
191 off += 3;
192 //xlog("\tDEBUG: Packet pin: %s\n", pin);
160 193
161 q = users_head;
162 while (q) {
163 k = q->head;
164 while (k) {
165 194 r = totp_verify(k->key, now30, k->ts / 30, pin); r = totp_verify(k->key, now30, k->ts / 30, pin);
166 195 if (r != 1) { if (r != 1) {
167 k = k->next;
196 xlog("\tDEBUG: pin does not match\n");
197 i++;
168 198 continue; continue;
169 199 } }
200 xlog("\tDEBUG: pin match\n");
201
202 cmd = data[off];
203 xlog("\tDEBUG: cmd=0x%02hhx\n", cmd);
170 204
171 205 k->ts = now; k->ts = now;
172 206
 
... ... static int test_2fa(const unsigned char *data, const unsigned int data_len,
190 224 key_save(q->uid, k); key_save(q->uid, k);
191 225 return cmd; return cmd;
192 226 } }
193
194 q = q->next;
227 k = k->next;
195 228 } }
229 q = q->next;
196 230 } }
197 231
198 232 return 0; return 0;
 
... ... static unsigned int process(const unsigned short eth,
325 359 return NF_ACCEPT; return NF_ACCEPT;
326 360 } }
327 361
328 xlog("\t%s: invalid command\n", ip);
362 xlog("\t%s: invalid command (%d)\n", ip, r);
329 363 return NF_DROP; return NF_DROP;
330 364 } }
331 365
 
... ... static int process_client(const unsigned int uid, unsigned char *buf,
474 508 unsigned char len, len2; unsigned char len, len2;
475 509 struct timeval now; struct timeval now;
476 510
477 if (n < 1)
478 break;
479
480 511 memset(&k, 0, sizeof(struct key)); memset(&k, 0, sizeof(struct key));
481 512
513 if (n < 1)
514 break;
482 515 len = buf[i++]; n--; len = buf[i++]; n--;
483 516 if (len > n) if (len > n)
484 517 break; break;
 
... ... static int process_client(const unsigned int uid, unsigned char *buf,
491 524 i += len; n -= len; i += len; n -= len;
492 525 //xlog("DEBUG: ENROLL name=[%s]\n", k.name); //xlog("DEBUG: ENROLL name=[%s]\n", k.name);
493 526
527 if (n < 1)
528 break;
529 len = buf[i++]; n--;
530 if (len > n)
531 break;
532 if (len > sizeof(k.pass) - 1)
533 len2 = sizeof(k.pass) - 1;
534 else
535 len2 = len;
536 memcpy(k.pass, buf + i, len2);
537 k.pass[len2] = '\0';
538 i += len; n -= len;
539 //xlog("DEBUG: ENROLL pass=[%s]\n", k.pass);
540
494 541 i = 1; /* we now overwrite the buffer */ i = 1; /* we now overwrite the buffer */
495 542
496 u = uid_to_user(uid); // TODO: use this anywhere
543 if (strlen(k.pass) < min_pass_len)
544 return i + protocol_enqueue_error(buf + i,
545 "password too short (minimum %hhu)", min_pass_len);
546
547 u = uid_to_user(uid);
497 548 if (!u) if (!u)
498 549 k.id = 0; k.id = 0;
499 550 else else
 
... ... static int process_client(const unsigned int uid, unsigned char *buf,
555 606
556 607 buf[i++] = 0x00; /* OK */ buf[i++] = 0x00; /* OK */
557 608
558 u = users_head;
559 while (u) {
560 if (u->uid == uid)
561 break;
562 }
609 u = uid_to_user(uid);
563 610 if (!u) if (!u)
564 611 return i; return i;
565 612
 
... ... static int process_client(const unsigned int uid, unsigned char *buf,
599 646 return i + protocol_enqueue_error(buf + i, key_error()); return i + protocol_enqueue_error(buf + i, key_error());
600 647
601 648 // Remove it from memory // Remove it from memory
602 u = users_head;
603 while (u) {
604 if (u->uid == uid)
605 break;
606 }
607 if (u) {
608 kprev = NULL;
609 k = u->head;
610 while (k) {
611 if (k->id != id) {
612 kprev = k;
613 k = k->next;
614 continue;
615 }
649 u = uid_to_user(uid);
650 if (!u)
651 return i + protocol_enqueue_error(buf + i,
652 "no enrollments found");
616 653
617 if (kprev)
618 kprev->next = k->next;
619 else
620 u->head = k->next;
621 free(k);
622 break;
654 kprev = NULL;
655 k = u->head;
656 while (k) {
657 if (k->id != id) {
658 kprev = k;
659 k = k->next;
660 continue;
623 661 } }
662
663 if (kprev)
664 kprev->next = k->next;
665 else
666 u->head = k->next;
667 free(k);
668 break;
624 669 } }
625 670
626 671 buf[i++] = 0x00; /* marks the success */ buf[i++] = 0x00; /* marks the success */
File protocol.c changed (mode: 100644) (index dd64b52..7c8e1a5)
1 1 #define _GNU_SOURCE #define _GNU_SOURCE
2 2
3 3 #include <string.h> #include <string.h>
4 #include <stdarg.h>
5 #include <stdio.h>
4 6
5 7 #include "protocol.h" #include "protocol.h"
6 8
7 9 /* /*
8 10 * Enqueues an error to user * Enqueues an error to user
9 11 */ */
10 unsigned short protocol_enqueue_string(unsigned char *buf, const char *s)
12 unsigned short protocol_enqueue_string(unsigned char *buf, const char *s, ...)
11 13 { {
12 14 unsigned short i = 0, len; unsigned short i = 0, len;
15 va_list ap;
16 char line[512];
13 17
14 buf[i++] = len = strlen(s);
15 memcpy(buf + i, s, len); i += len;
18 va_start(ap, s);
19 vsnprintf(line, sizeof(line), s, ap);
20 va_end(ap);
21
22 buf[i++] = len = strlen(line);
23 memcpy(buf + i, line, len); i += len;
16 24
17 25 return i; return i;
18 26 } }
 
... ... unsigned short protocol_enqueue_string(unsigned char *buf, const char *s)
20 28 /* /*
21 29 * Enqueues an error to user * Enqueues an error to user
22 30 */ */
23 unsigned short protocol_enqueue_error(unsigned char *buf, const char *error)
31 unsigned short protocol_enqueue_error(unsigned char *buf, const char *error, ...)
24 32 { {
25 unsigned short i = 0;
33 unsigned short i = 0, len;
34 va_list ap;
35 char line[512];
36
37 va_start(ap, error);
38 vsnprintf(line, sizeof(line), error, ap);
39 va_end(ap);
26 40
27 41 buf[i++] = 0x01; /* signaling error */ buf[i++] = 0x01; /* signaling error */
28 return i + protocol_enqueue_string(buf + i, error);
42 buf[i++] = len = strlen(line);
43 memcpy(buf + i, line, len); i += len;
44
45 return i;
29 46 } }
30 47
File protocol.h changed (mode: 100644) (index fd3f64a..bb07647)
1 1
2 unsigned short protocol_enqueue_string(unsigned char *buf, const char *error);
3 unsigned short protocol_enqueue_error(unsigned char *buf, const char *error);
2 unsigned short protocol_enqueue_string(unsigned char *buf, const char *error, ...);
3 unsigned short protocol_enqueue_error(unsigned char *buf, const char *error, ...);
4 4
File util.c changed (mode: 100644) (index 462577c..acb7e34)
2 2
3 3 #include <stdio.h> #include <stdio.h>
4 4 #include <stdarg.h> #include <stdarg.h>
5 #include <termios.h>
6 #include <unistd.h>
7 #include <string.h>
8 #include <errno.h>
5 9
6 10 #include "util.h" #include "util.h"
7 11
 
... ... void dump(const unsigned char *d, const unsigned int len)
50 54 xlog("\n"); xlog("\n");
51 55 } }
52 56
57 /*
58 * Reads a password from terminal
59 */
60 int read_password(const char *msg, char *pass, const size_t pass_size)
61 {
62 struct termios old, new;
63 int r;
64
65 printf("%s", msg); fflush(stdout);
66
67 r = tcgetattr(0, &old);
68 if (r == -1) {
69 fprintf(stderr, "Cannot call tcgetattr: %s\n", strerror(errno));
70 return -1;
71 }
72
73 new = old;
74 new.c_lflag &= ~ECHO;
75 r = tcsetattr(0, TCSAFLUSH, &new);
76 if (r == -1) {
77 fprintf(stderr, "Cannot call tcsetattr: %s\n", strerror(errno));
78 return -1;
79 }
80
81 while (1) {
82 r = read(0, pass, pass_size - 1);
83 if (r == -1) {
84 fprintf(stderr, "Cannot read password: %s\n", strerror(errno));
85 break;
86 }
87
88 while ((r > 0) && (strchr("\r\n \t", pass[r - 1]))) {
89 pass[r - 1] = '\0';
90 r--;
91 }
92
93 break;
94 }
95 tcsetattr(0, TCSAFLUSH, &old);
96
97 printf("\n");
98
99 return r;
100 }
File util.h changed (mode: 100644) (index a6a603f..1bc6698)
1 1 void xlog(const char *format, ...); void xlog(const char *format, ...);
2 2 void xerr(const char *format, ...); void xerr(const char *format, ...);
3 3 void dump(const unsigned char *d, const unsigned int len); void dump(const unsigned char *d, const unsigned int len);
4 int read_password(const char *msg, char *pass, const size_t pass_size);
5
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/catalinux/nf2fa

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/catalinux/nf2fa

Clone this repository using git:
git clone git://git.rocketgit.com/user/catalinux/nf2fa

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main