2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Simon Josefsson
3 * Copyright (C) 2001,2003 Nikos Mavrogiannopoulos
4 * Copyright (C) 2004 Free Software Foundation
6 * This file is part of GNUTLS.
8 * GNUTLS is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * GNUTLS is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31 main (int argc
, char **argv
)
33 printf ("\nSRP not supported. This program is a dummy.\n\n");
38 srptool_version (void)
40 fprintf (stderr
, "GNU TLS dummy srptool.\n");
48 #include <gnutls/gnutls.h>
49 #include <gnutls/extra.h>
50 #include <crypt-gaa.h>
52 #include <gc.h> /* for randomize */
54 #include <sys/types.h>
64 /* Gnulib portability files. */
67 #define _MAX(x,y) (x>y?x:y)
69 /* This may need some rewrite. A lot of stuff which should be here
70 * are in the library, which is not good.
73 int crypt_int (const char *username
, const char *passwd
, int salt
,
74 char *tpasswd_conf
, char *tpasswd
, int uindex
);
75 static int read_conf_values (gnutls_datum_t
* g
, gnutls_datum_t
* n
, char *str
);
76 static int _verify_passwd_int (const char *username
, const char *passwd
,
77 char *verifier
, char *salt
,
78 const gnutls_datum_t
* g
,
79 const gnutls_datum_t
* n
);
82 srptool_version (void)
84 const char *v
= gnutls_check_version (NULL
);
86 printf ("srptool (GnuTLS) %s\n", LIBGNUTLS_VERSION
);
87 if (strcmp (v
, LIBGNUTLS_VERSION
) != 0)
88 printf ("libgnutls %s\n", v
);
93 print_num (const char *msg
, const gnutls_datum_t
* num
)
97 printf ("%s:\t", msg
);
99 for (i
= 0; i
< num
->size
; i
++)
101 if (i
!= 0 && i
% 12 == 0)
103 else if (i
!= 0 && i
!= num
->size
)
105 printf ("%.2x", num
->data
[i
]);
112 generate_create_conf (char *tpasswd_conf
)
118 gnutls_datum_t str_g
, str_n
;
120 fd
= fopen (tpasswd_conf
, "w");
123 fprintf (stderr
, "Cannot open file '%s'\n", tpasswd_conf
);
127 for (index
= 1; index
<= 3; index
++)
132 n
= gnutls_srp_1024_group_prime
;
133 g
= gnutls_srp_1024_group_generator
;
137 n
= gnutls_srp_1536_group_prime
;
138 g
= gnutls_srp_1536_group_generator
;
142 n
= gnutls_srp_2048_group_prime
;
143 g
= gnutls_srp_2048_group_generator
;
146 printf ("\nGroup %d, of %d bits:\n", index
, n
.size
* 8);
147 print_num ("Generator", &g
);
148 print_num ("Prime", &n
);
150 if (gnutls_srp_base64_encode_alloc (&n
, &str_n
) < 0)
152 fprintf (stderr
, "Could not encode\n");
156 if (gnutls_srp_base64_encode_alloc (&g
, &str_g
) < 0)
158 fprintf (stderr
, "Could not encode\n");
162 sprintf (line
, "%d:%s:%s\n", index
, str_n
.data
, str_g
.data
);
164 gnutls_free (str_n
.data
);
165 gnutls_free (str_g
.data
);
167 fwrite (line
, 1, strlen (line
), fd
);
177 /* The format of a tpasswd file is:
178 * username:verifier:salt:index
180 * index is the index of the prime-generator pair in tpasswd.conf
183 _verify_passwd_int (const char *username
, const char *passwd
,
184 char *verifier
, char *salt
,
185 const gnutls_datum_t
* g
, const gnutls_datum_t
* n
)
188 gnutls_datum_t tmp
, raw_salt
, new_verifier
;
192 if (salt
== NULL
|| verifier
== NULL
)
195 /* copy salt, and null terminate after the ':' */
196 strcpy (_salt
, salt
);
197 pos
= strchr (_salt
, ':');
201 /* convert salt to binary. */
203 tmp
.size
= strlen (_salt
);
205 if (gnutls_srp_base64_decode_alloc (&tmp
, &raw_salt
) < 0)
207 fprintf (stderr
, "Could not decode salt.\n");
211 if (gnutls_srp_verifier
212 (username
, passwd
, &raw_salt
, g
, n
, &new_verifier
) < 0)
214 fprintf (stderr
, "Could not make the verifier\n");
218 free (raw_salt
.data
);
220 /* encode the verifier into _salt */
221 salt_size
= sizeof (_salt
);
222 if (gnutls_srp_base64_encode (&new_verifier
, _salt
, &salt_size
) < 0)
224 fprintf (stderr
, "Encoding error\n");
228 free (new_verifier
.data
);
230 if (strncmp (verifier
, _salt
, strlen (_salt
)) == 0)
232 fprintf (stderr
, "Password verified\n");
237 fprintf (stderr
, "Password does NOT match\n");
243 filecopy (char *src
, char *dst
)
249 fd
= fopen (dst
, "w");
252 fprintf (stderr
, "Cannot open '%s' for write\n", dst
);
256 fd2
= fopen (src
, "r");
264 line
[sizeof (line
) - 1] = 0;
267 p
= fgets (line
, sizeof (line
) - 1, fd2
);
281 /* accepts password file */
283 find_strchr (char *username
, char *file
)
290 fd
= fopen (file
, "r");
293 fprintf (stderr
, "Cannot open file '%s'\n", file
);
297 while (fgets (line
, sizeof (line
), fd
) != NULL
)
299 /* move to first ':' */
301 while ((line
[i
] != ':') && (line
[i
] != '\0') && (i
< sizeof (line
)))
305 if (strncmp (username
, line
, _MAX (i
, strlen (username
))) == 0)
308 pos
= strrchr (line
, ':');
319 /* Parses the tpasswd files, in order to verify the given
320 * username/password pair.
323 verify_passwd (char *conffile
, char *tpasswd
, char *username
,
333 iindex
= find_strchr (username
, tpasswd
);
336 fprintf (stderr
, "Cannot find '%s' in %s\n", username
, tpasswd
);
340 fd
= fopen (conffile
, "r");
343 fprintf (stderr
, "Cannot find %s\n", conffile
);
349 p
= fgets (line
, sizeof (line
) - 1, fd
);
351 while (p
!= NULL
&& atoi (p
) != iindex
);
355 fprintf (stderr
, "Cannot find entry in %s\n", conffile
);
358 line
[sizeof (line
) - 1] = 0;
362 if ((iindex
= read_conf_values (&g
, &n
, line
)) < 0)
364 fprintf (stderr
, "Cannot parse conf file '%s'\n", conffile
);
368 fd
= fopen (tpasswd
, "r");
371 fprintf (stderr
, "Cannot open file '%s'\n", tpasswd
);
375 while (fgets (line
, sizeof (line
), fd
) != NULL
)
378 * This is the actual verifier.
381 while ((line
[i
] != ':') && (line
[i
] != '\0') && (i
< sizeof (line
)))
385 if (strncmp (username
, line
, _MAX (i
, strlen (username
))) == 0)
387 char *verifier_pos
, *salt_pos
;
389 pos
= strchr (line
, ':');
393 fprintf (stderr
, "Cannot parse conf file '%s'\n", conffile
);
399 /* Move to the salt */
400 pos
= strchr (pos
, ':');
403 fprintf (stderr
, "Cannot parse conf file '%s'\n", conffile
);
409 return _verify_passwd_int (username
, passwd
,
410 verifier_pos
, salt_pos
, &g
, &n
);
419 #define KPASSWD "/etc/tpasswd"
420 #define KPASSWD_CONF "/etc/tpasswd.conf"
423 main (int argc
, char **argv
)
430 if ((ret
= gnutls_global_init ()) < 0)
432 fprintf (stderr
, "global_init: %s\n", gnutls_strerror (ret
));
438 if (gaa (argc
, argv
, &info
) != -1)
440 fprintf (stderr
, "Error in the arguments.\n");
446 if (info
.create_conf
!= NULL
)
448 return generate_create_conf (info
.create_conf
);
451 if (info
.passwd
== NULL
)
452 info
.passwd
= KPASSWD
;
453 if (info
.passwd_conf
== NULL
)
454 info
.passwd_conf
= KPASSWD_CONF
;
456 if (info
.username
== NULL
)
459 pwd
= getpwuid (getuid ());
463 fprintf (stderr
, "No such user\n");
467 info
.username
= pwd
->pw_name
;
469 fprintf (stderr
, "Please specify a user\n");
476 passwd
= getpass ("Enter password: ");
479 fprintf (stderr
, "Please specify a password\n");
484 if (info
.verify
!= 0)
486 return verify_passwd (info
.passwd_conf
, info
.passwd
,
487 info
.username
, passwd
);
491 return crypt_int (info
.username
, passwd
, salt
,
492 info
.passwd_conf
, info
.passwd
, info
.index
);
497 _srp_crypt (const char *username
, const char *passwd
, int salt_size
,
498 const gnutls_datum_t
* g
, const gnutls_datum_t
* n
)
501 static char result
[1024];
502 gnutls_datum_t dat_salt
, txt_salt
;
503 gnutls_datum_t verifier
, txt_verifier
;
505 if ((unsigned) salt_size
> sizeof (salt
))
510 if (gc_nonce (salt
, salt_size
) != GC_OK
)
512 fprintf (stderr
, "Could not create nonce\n");
516 dat_salt
.data
= salt
;
517 dat_salt
.size
= salt_size
;
519 if (gnutls_srp_verifier (username
, passwd
, &dat_salt
, g
, n
, &verifier
) < 0)
521 fprintf (stderr
, "Error getting verifier\n");
525 /* base64 encode the verifier */
526 if (gnutls_srp_base64_encode_alloc (&verifier
, &txt_verifier
) < 0)
528 fprintf (stderr
, "Error encoding\n");
529 free (verifier
.data
);
533 free (verifier
.data
);
535 if (gnutls_srp_base64_encode_alloc (&dat_salt
, &txt_salt
) < 0)
537 fprintf (stderr
, "Error encoding\n");
541 sprintf (result
, "%s:%s", txt_verifier
.data
, txt_salt
.data
);
542 free (txt_salt
.data
);
543 free (txt_verifier
.data
);
551 crypt_int (const char *username
, const char *passwd
, int salt_size
,
552 char *tpasswd_conf
, char *tpasswd
, int uindex
)
562 fd
= fopen (tpasswd_conf
, "r");
565 fprintf (stderr
, "Cannot find %s\n", tpasswd_conf
);
570 { /* find the specified uindex in file */
571 p
= fgets (line
, sizeof (line
) - 1, fd
);
574 while (p
!= NULL
&& iindex
!= uindex
);
578 fprintf (stderr
, "Cannot find entry in %s\n", tpasswd_conf
);
581 line
[sizeof (line
) - 1] = 0;
584 if ((iindex
= read_conf_values (&g
, &n
, line
)) < 0)
586 fprintf (stderr
, "Cannot parse conf file '%s'\n", tpasswd_conf
);
590 cr
= _srp_crypt (username
, passwd
, salt_size
, &g
, &n
);
593 fprintf (stderr
, "Cannot _srp_crypt()...\n");
598 /* delete previous entry */
603 if (strlen (tpasswd
) > sizeof (tmpname
) + 5)
605 fprintf (stderr
, "file '%s' is tooooo long\n", tpasswd
);
608 strcpy (tmpname
, tpasswd
);
609 strcat (tmpname
, ".tmp");
611 if (stat (tmpname
, &st
) != -1)
613 fprintf (stderr
, "file '%s' is locked\n", tpasswd
);
617 if (filecopy (tpasswd
, tmpname
) != 0)
619 fprintf (stderr
, "Cannot copy '%s' to '%s'\n", tpasswd
, tmpname
);
623 fd
= fopen (tpasswd
, "w");
626 fprintf (stderr
, "Cannot open '%s' for write\n", tpasswd
);
631 fd2
= fopen (tmpname
, "r");
634 fprintf (stderr
, "Cannot open '%s' for read\n", tmpname
);
642 p
= fgets (line
, sizeof (line
) - 1, fd2
);
646 pp
= strchr (line
, ':');
652 _MAX (strlen (username
), (unsigned int) (pp
- p
))) == 0)
655 fprintf (fd
, "%s:%s:%u\n", username
, cr
, iindex
);
666 fprintf (fd
, "%s:%s:%u\n", username
, cr
, iindex
);
682 /* this function parses tpasswd.conf file. Format is:
683 * int(index):base64(n):base64(g)
686 read_conf_values (gnutls_datum_t
* g
, gnutls_datum_t
* n
, char *str
)
695 p
= strrchr (str
, ':'); /* we have g */
704 /* read the generator */
706 if (p
[len
- 1] == '\n')
711 ret
= gnutls_srp_base64_decode_alloc (&dat
, g
);
715 fprintf (stderr
, "Decoding error\n");
719 /* now go for n - modulo */
720 p
= strrchr (str
, ':'); /* we have n */
730 dat
.size
= strlen (p
);
732 ret
= gnutls_srp_base64_decode_alloc (&dat
, n
);
736 fprintf (stderr
, "Decoding error\n");
744 #endif /* ENABLE_SRP */