Bug Summary

File:src/srptool.c
Location:line 351, column 8
Description:Although the value stored to 'iindex' is used in the enclosing expression, the value is never actually read from 'iindex'

Annotated Source Code

1/*
2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
3 *
4 * This file is part of GnuTLS.
5 *
6 * GnuTLS is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GnuTLS is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see
18 * <http://www.gnu.org/licenses/>.
19 */
20
21#include <config.h>
22
23#include <stdio.h>
24#include <string.h>
25#include <stdlib.h>
26#include <gnutls/gnutls.h>
27#include <srptool-gaa.h>
28#include <gnutls/crypto.h> /* for random */
29
30#include <sys/types.h>
31#include <sys/stat.h>
32
33#ifndef _WIN32
34#include <pwd.h>
35#include <unistd.h>
36#else
37#include <windows.h>
38#endif
39
40/* Gnulib portability files. */
41#include <getpass.h>
42#include <minmax.h>
43#include <progname.h>
44#include <version-etc.h>
45
46/* This may need some rewrite. A lot of stuff which should be here
47 * are in the library, which is not good.
48 */
49
50int crypt_int (const char *username, const char *passwd, int salt,
51 char *tpasswd_conf, char *tpasswd, int uindex);
52static int read_conf_values (gnutls_datum_t * g, gnutls_datum_t * n,
53 char *str);
54static int _verify_passwd_int (const char *username, const char *passwd,
55 char *verifier, char *salt,
56 const gnutls_datum_t * g,
57 const gnutls_datum_t * n);
58
59static void
60print_num (const char *msg, const gnutls_datum_t * num)
61{
62 unsigned int i;
63
64 printf ("%s:\t", msg);
65
66 for (i = 0; i < num->size; i++)
67 {
68 if (i != 0 && i % 12 == 0)
69 printf ("\n\t");
70 else if (i != 0 && i != num->size)
71 printf (":");
72 printf ("%.2x", num->data[i]);
73 }
74 printf ("\n\n");
75
76}
77
78static int
79generate_create_conf (char *tpasswd_conf)
80{
81 FILE *fd;
82 char line[5 * 1024];
83 int index = 1;
84 gnutls_datum_t g, n;
85 gnutls_datum_t str_g, str_n;
86
87 fd = fopen (tpasswd_conf, "w");
88 if (fd == NULL((void*)0))
89 {
90 fprintf (stderrstderr, "Cannot open file '%s'\n", tpasswd_conf);
91 return -1;
92 }
93
94 for (index = 1; index <= 5; index++)
95 {
96
97 if (index == 1)
98 {
99 n = gnutls_srp_1024_group_prime;
100 g = gnutls_srp_1024_group_generator;
101 }
102 else if (index == 2)
103 {
104 n = gnutls_srp_1536_group_prime;
105 g = gnutls_srp_1536_group_generator;
106 }
107 else if (index == 3)
108 {
109 n = gnutls_srp_2048_group_prime;
110 g = gnutls_srp_2048_group_generator;
111 }
112 else if (index == 4)
113 {
114 n = gnutls_srp_3072_group_prime;
115 g = gnutls_srp_3072_group_generator;
116 }
117 else if (index == 5)
118 {
119 n = gnutls_srp_4096_group_prime;
120 g = gnutls_srp_4096_group_generator;
121 }
122 else
123 {
124 fprintf(stderrstderr, "Unknown index: %d\n", index);
125 return -1;
126 }
127
128 printf ("\nGroup %d, of %d bits:\n", index, n.size * 8);
129 print_num ("Generator", &g);
130 print_num ("Prime", &n);
131
132 if (gnutls_srp_base64_encode_alloc (&n, &str_n) < 0)
133 {
134 fprintf (stderrstderr, "Could not encode\n");
135 return -1;
136 }
137
138 if (gnutls_srp_base64_encode_alloc (&g, &str_g) < 0)
139 {
140 fprintf (stderrstderr, "Could not encode\n");
141 return -1;
142 }
143
144 sprintf (line, "%d:%s:%s\n", index, str_n.data, str_g.data);
145
146 gnutls_free (str_n.data);
147 gnutls_free (str_g.data);
148
149 fwrite (line, 1, strlen (line), fd);
150
151 }
152
153 fclose (fd);
154
155 return 0;
156
157}
158
159/* The format of a tpasswd file is:
160 * username:verifier:salt:index
161 *
162 * index is the index of the prime-generator pair in tpasswd.conf
163 */
164static int
165_verify_passwd_int (const char *username, const char *passwd,
166 char *verifier, char *salt,
167 const gnutls_datum_t * g, const gnutls_datum_t * n)
168{
169 char _salt[1024];
170 gnutls_datum_t tmp, raw_salt, new_verifier;
171 size_t salt_size;
172 char *pos;
173
174 if (salt == NULL((void*)0) || verifier == NULL((void*)0))
175 return -1;
176
177 if (strlen(salt) >= sizeof(_salt))
178 {
179 fprintf (stderrstderr, "Too long salt.\n");
180 return -1;
181 }
182
183 /* copy salt, and null terminate after the ':' */
184 strcpy (_salt, salt);
185 pos = strchr (_salt, ':');
186 if (pos != NULL((void*)0))
187 *pos = 0;
188
189 /* convert salt to binary. */
190 tmp.data = _salt;
191 tmp.size = strlen (_salt);
192
193 if (gnutls_srp_base64_decode_alloc (&tmp, &raw_salt) < 0)
194 {
195 fprintf (stderrstderr, "Could not decode salt.\n");
196 return -1;
197 }
198
199 if (gnutls_srp_verifier
200 (username, passwd, &raw_salt, g, n, &new_verifier) < 0)
201 {
202 fprintf (stderrstderr, "Could not make the verifier\n");
203 return -1;
204 }
205
206 free (raw_salt.data);
207
208 /* encode the verifier into _salt */
209 salt_size = sizeof (_salt);
210 memset (_salt, 0, salt_size);
211 if (gnutls_srp_base64_encode (&new_verifier, _salt, &salt_size) < 0)
212 {
213 fprintf (stderrstderr, "Encoding error\n");
214 return -1;
215 }
216
217 free (new_verifier.data);
218
219 if (strncmp (verifier, _salt, strlen (_salt)) == 0)
220 {
221 fprintf (stderrstderr, "Password verified\n");
222 return 0;
223 }
224 else
225 {
226 fprintf (stderrstderr, "Password does NOT match\n");
227 }
228 return -1;
229}
230
231static int
232filecopy (char *src, char *dst)
233{
234 FILE *fd, *fd2;
235 char line[5 * 1024];
236 char *p;
237
238 fd = fopen (dst, "w");
239 if (fd == NULL((void*)0))
240 {
241 fprintf (stderrstderr, "Cannot open '%s' for write\n", dst);
242 return -1;
243 }
244
245 fd2 = fopen (src, "r");
246 if (fd2 == NULL((void*)0))
247 {
248 /* empty file */
249 fclose (fd);
250 return 0;
251 }
252
253 line[sizeof (line) - 1] = 0;
254 do
255 {
256 p = fgets (line, sizeof (line) - 1, fd2);
257 if (p == NULL((void*)0))
258 break;
259
260 fputs (line, fd);
261 }
262 while (1);
263
264 fclose (fd);
265 fclose (fd2);
266
267 return 0;
268}
269
270/* accepts password file */
271static int
272find_strchr (char *username, char *file)
273{
274 FILE *fd;
275 char *pos;
276 char line[5 * 1024];
277 unsigned int i;
278
279 fd = fopen (file, "r");
280 if (fd == NULL((void*)0))
281 {
282 fprintf (stderrstderr, "Cannot open file '%s'\n", file);
283 return -1;
284 }
285
286 while (fgets (line, sizeof (line), fd) != NULL((void*)0))
287 {
288 /* move to first ':' */
289 i = 0;
290 while ((line[i] != ':') && (line[i] != '\0') && (i < sizeof (line)))
291 {
292 i++;
293 }
294 if (strncmp (username, line, MAX (i, strlen (username))(((i)>(strlen (username)))?(i):(strlen (username)))) == 0)
295 {
296 /* find the index */
297 pos = strrchr (line, ':');
298 pos++;
299 fclose (fd);
300 return atoi (pos);
301 }
302 }
303
304 fclose (fd);
305 return -1;
306}
307
308/* Parses the tpasswd files, in order to verify the given
309 * username/password pair.
310 */
311static int
312verify_passwd (char *conffile, char *tpasswd, char *username,
313 const char *passwd)
314{
315 FILE *fd;
316 char line[5 * 1024];
317 unsigned int i;
318 gnutls_datum_t g, n;
319 int iindex;
320 char *p, *pos;
321
322 iindex = find_strchr (username, tpasswd);
323 if (iindex == -1)
324 {
325 fprintf (stderrstderr, "Cannot find '%s' in %s\n", username, tpasswd);
326 return -1;
327 }
328
329 fd = fopen (conffile, "r");
330 if (fd == NULL((void*)0))
331 {
332 fprintf (stderrstderr, "Cannot find %s\n", conffile);
333 return -1;
334 }
335
336 do
337 {
338 p = fgets (line, sizeof (line) - 1, fd);
339 }
340 while (p != NULL((void*)0) && atoi (p) != iindex);
341
342 if (p == NULL((void*)0))
343 {
344 fprintf (stderrstderr, "Cannot find entry in %s\n", conffile);
345 return -1;
346 }
347 line[sizeof (line) - 1] = 0;
348
349 fclose (fd);
350
351 if ((iindex = read_conf_values (&g, &n, line)) < 0)
Although the value stored to 'iindex' is used in the enclosing expression, the value is never actually read from 'iindex'
352 {
353 fprintf (stderrstderr, "Cannot parse conf file '%s'\n", conffile);
354 return -1;
355 }
356
357 fd = fopen (tpasswd, "r");
358 if (fd == NULL((void*)0))
359 {
360 fprintf (stderrstderr, "Cannot open file '%s'\n", tpasswd);
361 return -1;
362 }
363
364 while (fgets (line, sizeof (line), fd) != NULL((void*)0))
365 {
366 /* move to first ':'
367 * This is the actual verifier.
368 */
369 i = 0;
370 while ((line[i] != ':') && (line[i] != '\0') && (i < sizeof (line)))
371 {
372 i++;
373 }
374 if (strncmp (username, line, MAX (i, strlen (username))(((i)>(strlen (username)))?(i):(strlen (username)))) == 0)
375 {
376 char *verifier_pos, *salt_pos;
377
378 pos = strchr (line, ':');
379 fclose (fd);
380 if (pos == NULL((void*)0))
381 {
382 fprintf (stderrstderr, "Cannot parse conf file '%s'\n", conffile);
383 return -1;
384 }
385 pos++;
386 verifier_pos = pos;
387
388 /* Move to the salt */
389 pos = strchr (pos, ':');
390 if (pos == NULL((void*)0))
391 {
392 fprintf (stderrstderr, "Cannot parse conf file '%s'\n", conffile);
393 return -1;
394 }
395 pos++;
396 salt_pos = pos;
397
398 return _verify_passwd_int (username, passwd,
399 verifier_pos, salt_pos, &g, &n);
400 }
401 }
402
403 fclose (fd);
404 return -1;
405
406}
407
408#define KPASSWD"/etc/tpasswd" "/etc/tpasswd"
409#define KPASSWD_CONF"/etc/tpasswd.conf" "/etc/tpasswd.conf"
410
411static void
412tls_log_func (int level, const char *str)
413{
414 fprintf (stderrstderr, "|<%d>| %s", level, str);
415}
416
417int main (int argc, char **argv)
418{
419 gaainfo info;
420 const char *passwd;
421 int salt_size, ret;
422#ifndef _WIN32
423 struct passwd *pwd;
424#endif
425
426 set_program_name (argv[0]);
427
428 if ((ret = gnutls_global_init ()) < 0)
429 {
430 fprintf (stderrstderr, "global_init: %s\n", gnutls_strerror (ret));
431 exit (1);
432 }
433
434 umask (066);
435
436 if (gaa (argc, argv, &info) != -1)
437 {
438 fprintf (stderrstderr, "Error in the arguments.\n");
439 return -1;
440 }
441
442 gnutls_global_set_log_function (tls_log_func);
443 gnutls_global_set_log_level (info.debug);
444
445 if (info.create_conf != NULL((void*)0))
446 {
447 return generate_create_conf (info.create_conf);
448 }
449
450 if (info.passwd == NULL((void*)0))
451 info.passwd = (char *) KPASSWD"/etc/tpasswd";
452 if (info.passwd_conf == NULL((void*)0))
453 info.passwd_conf = (char *) KPASSWD_CONF"/etc/tpasswd.conf";
454
455 if (info.username == NULL((void*)0))
456 {
457#ifndef _WIN32
458 pwd = getpwuid (getuid ());
459
460 if (pwd == NULL((void*)0))
461 {
462 fprintf (stderrstderr, "No such user\n");
463 return -1;
464 }
465
466 info.username = pwd->pw_name;
467#else
468 fprintf (stderrstderr, "Please specify a user\n");
469 return -1;
470#endif
471 }
472
473 salt_size = 16;
474
475 passwd = getpass ("Enter password: ");
476 if (passwd == NULL((void*)0))
477 {
478 fprintf (stderrstderr, "Please specify a password\n");
479 return -1;
480 }
481
482/* not ready yet */
483 if (info.verify != 0)
484 {
485 return verify_passwd (info.passwd_conf, info.passwd,
486 info.username, passwd);
487 }
488
489
490 return crypt_int (info.username, passwd, salt_size,
491 info.passwd_conf, info.passwd, info.index);
492
493}
494
495static char *
496_srp_crypt (const char *username, const char *passwd, int salt_size,
497 const gnutls_datum_t * g, const gnutls_datum_t * n)
498{
499 char salt[128];
500 static char result[1024];
501 gnutls_datum_t dat_salt, txt_salt;
502 gnutls_datum_t verifier, txt_verifier;
503
504 if ((unsigned) salt_size > sizeof (salt))
505 return NULL((void*)0);
506
507 /* generate the salt
508 */
509 if (gnutls_rnd (GNUTLS_RND_NONCE, salt, salt_size) < 0)
510 {
511 fprintf (stderrstderr, "Could not create nonce\n");
512 return NULL((void*)0);
513 }
514
515 dat_salt.data = salt;
516 dat_salt.size = salt_size;
517
518 if (gnutls_srp_verifier (username, passwd, &dat_salt, g, n, &verifier) < 0)
519 {
520 fprintf (stderrstderr, "Error getting verifier\n");
521 return NULL((void*)0);
522 }
523
524 /* base64 encode the verifier */
525 if (gnutls_srp_base64_encode_alloc (&verifier, &txt_verifier) < 0)
526 {
527 fprintf (stderrstderr, "Error encoding\n");
528 free (verifier.data);
529 return NULL((void*)0);
530 }
531
532 free (verifier.data);
533
534 if (gnutls_srp_base64_encode_alloc (&dat_salt, &txt_salt) < 0)
535 {
536 fprintf (stderrstderr, "Error encoding\n");
537 return NULL((void*)0);
538 }
539
540 sprintf (result, "%s:%s", txt_verifier.data, txt_salt.data);
541 free (txt_salt.data);
542 free (txt_verifier.data);
543
544 return result;
545
546}
547
548
549int
550crypt_int (const char *username, const char *passwd, int salt_size,
551 char *tpasswd_conf, char *tpasswd, int uindex)
552{
553 FILE *fd;
554 char *cr;
555 gnutls_datum_t g, n;
556 char line[5 * 1024];
557 char *p, *pp;
558 int iindex;
559 char tmpname[1024];
560
561 fd = fopen (tpasswd_conf, "r");
562 if (fd == NULL((void*)0))
563 {
564 fprintf (stderrstderr, "Cannot find %s\n", tpasswd_conf);
565 return -1;
566 }
567
568 do
569 { /* find the specified uindex in file */
570 p = fgets (line, sizeof (line) - 1, fd);
571 iindex = atoi (p);
572 }
573 while (p != NULL((void*)0) && iindex != uindex);
574
575 if (p == NULL((void*)0))
576 {
577 fprintf (stderrstderr, "Cannot find entry in %s\n", tpasswd_conf);
578 return -1;
579 }
580 line[sizeof (line) - 1] = 0;
581
582 fclose (fd);
583 if ((iindex = read_conf_values (&g, &n, line)) < 0)
584 {
585 fprintf (stderrstderr, "Cannot parse conf file '%s'\n", tpasswd_conf);
586 return -1;
587 }
588
589 cr = _srp_crypt (username, passwd, salt_size, &g, &n);
590 if (cr == NULL((void*)0))
591 {
592 fprintf (stderrstderr, "Cannot _srp_crypt()...\n");
593 return -1;
594 }
595 else
596 {
597 /* delete previous entry */
598 struct stat st;
599 FILE *fd2;
600 int put;
601
602 if (strlen (tpasswd) > sizeof (tmpname) + 5)
603 {
604 fprintf (stderrstderr, "file '%s' is tooooo long\n", tpasswd);
605 return -1;
606 }
607 strcpy (tmpname, tpasswd);
608 strcat (tmpname, ".tmp");
609
610 if (stat (tmpname, &st) != -1)
611 {
612 fprintf (stderrstderr, "file '%s' is locked\n", tpasswd);
613 return -1;
614 }
615
616 if (filecopy (tpasswd, tmpname) != 0)
617 {
618 fprintf (stderrstderr, "Cannot copy '%s' to '%s'\n", tpasswd, tmpname);
619 return -1;
620 }
621
622 fd = fopen (tpasswd, "w");
623 if (fd == NULL((void*)0))
624 {
625 fprintf (stderrstderr, "Cannot open '%s' for write\n", tpasswd);
626 remove (tmpname);
627 return -1;
628 }
629
630 fd2 = fopen (tmpname, "r");
631 if (fd2 == NULL((void*)0))
632 {
633 fprintf (stderrstderr, "Cannot open '%s' for read\n", tmpname);
634 remove (tmpname);
635 return -1;
636 }
637
638 put = 0;
639 do
640 {
641 p = fgets (line, sizeof (line) - 1, fd2);
642 if (p == NULL((void*)0))
643 break;
644
645 pp = strchr (line, ':');
646 if (pp == NULL((void*)0))
647 continue;
648
649 if (strncmp (p, username,
650 MAX (strlen (username), (unsigned int) (pp - p))(((strlen (username))>((unsigned int) (pp - p)))?(strlen (
username)):((unsigned int) (pp - p)))
) == 0)
651 {
652 put = 1;
653 fprintf (fd, "%s:%s:%u\n", username, cr, iindex);
654 }
655 else
656 {
657 fputs (line, fd);
658 }
659 }
660 while (1);
661
662 if (put == 0)
663 {
664 fprintf (fd, "%s:%s:%u\n", username, cr, iindex);
665 }
666
667 fclose (fd);
668 fclose (fd2);
669
670 remove (tmpname);
671
672 }
673
674
675 return 0;
676}
677
678
679
680/* this function parses tpasswd.conf file. Format is:
681 * int(index):base64(n):base64(g)
682 */
683static int
684read_conf_values (gnutls_datum_t * g, gnutls_datum_t * n, char *str)
685{
686 char *p;
687 int len;
688 int index, ret;
689 gnutls_datum_t dat;
690
691 index = atoi (str);
692
693 p = strrchr (str, ':'); /* we have g */
694 if (p == NULL((void*)0))
695 {
696 return -1;
697 }
698
699 *p = '\0';
700 p++;
701
702 /* read the generator */
703 len = strlen (p);
704 if (p[len - 1] == '\n')
705 len--;
706
707 dat.data = p;
708 dat.size = len;
709 ret = gnutls_srp_base64_decode_alloc (&dat, g);
710
711 if (ret < 0)
712 {
713 fprintf (stderrstderr, "Decoding error\n");
714 return -1;
715 }
716
717 /* now go for n - modulo */
718 p = strrchr (str, ':'); /* we have n */
719 if (p == NULL((void*)0))
720 {
721 return -1;
722 }
723
724 *p = '\0';
725 p++;
726
727 dat.data = p;
728 dat.size = strlen (p);
729
730 ret = gnutls_srp_base64_decode_alloc (&dat, n);
731
732 if (ret < 0)
733 {
734 fprintf (stderrstderr, "Decoding error\n");
735 free (g->data);
736 return -1;
737 }
738
739 return index;
740}
741
742extern void srptool_version (void);
743
744void
745srptool_version (void)
746{
747 const char *p = PACKAGE_NAME"GnuTLS";
748 if (strcmp (gnutls_check_version (NULL((void*)0)), PACKAGE_VERSION"3.0.12") != 0)
749 p = PACKAGE_STRING"GnuTLS 3.0.12";
750 version_etc (stdoutstdout, "srptool", p, gnutls_check_version (NULL((void*)0)),
751 "Nikos Mavrogiannopoulos", (char *) NULL((void*)0));
752}