2 * Copyright (C) 2004, 2005, 2006, 2007 Simon Josefsson
3 * Copyright (C) 2001,2003 Nikos Mavroyanopoulos
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 2 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, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
32 main (int argc
, char **argv
)
34 printf ("\nSRP not supported. This program is a dummy.\n\n");
39 srptool_version (void)
41 fprintf (stderr
, "GNU TLS dummy srptool.\n");
49 #include <gnutls/gnutls.h>
50 #include <gnutls/extra.h>
51 #include <crypt-gaa.h>
53 #include <gc.h> /* for randomize */
55 #include <sys/types.h>
65 /* Gnulib portability files. */
68 #define _MAX(x,y) (x>y?x:y)
70 /* This may need some rewrite. A lot of stuff which should be here
71 * are in the library, which is not good.
74 int crypt_int (const char *username
, const char *passwd
, int salt
,
75 char *tpasswd_conf
, char *tpasswd
, int uindex
);
76 static int read_conf_values (gnutls_datum_t
* g
, gnutls_datum_t
* n
, char *str
);
77 static int _verify_passwd_int (const char *username
, const char *passwd
,
78 char *verifier
, char *salt
,
79 const gnutls_datum_t
* g
,
80 const gnutls_datum_t
* n
);
83 srptool_version (void)
85 const char *v
= gnutls_check_version (NULL
);
87 printf ("srptool (GnuTLS) %s\n", LIBGNUTLS_VERSION
);
88 if (strcmp (v
, LIBGNUTLS_VERSION
) != 0)
89 printf ("libgnutls %s\n", v
);
94 print_num (const char *msg
, const gnutls_datum_t
* num
)
98 printf ("%s:\t", msg
);
100 for (i
= 0; i
< num
->size
; i
++)
102 if (i
!= 0 && i
% 12 == 0)
104 else if (i
!= 0 && i
!= num
->size
)
106 printf ("%.2x", num
->data
[i
]);
113 generate_create_conf (char *tpasswd_conf
)
119 gnutls_datum_t str_g
, str_n
;
121 fd
= fopen (tpasswd_conf
, "w");
124 fprintf (stderr
, "Cannot open file '%s'\n", tpasswd_conf
);
128 for (index
= 1; index
<= 3; index
++)
133 n
= gnutls_srp_1024_group_prime
;
134 g
= gnutls_srp_1024_group_generator
;
138 n
= gnutls_srp_1536_group_prime
;
139 g
= gnutls_srp_1536_group_generator
;
143 n
= gnutls_srp_2048_group_prime
;
144 g
= gnutls_srp_2048_group_generator
;
147 printf ("\nGroup %d, of %d bits:\n", index
, n
.size
* 8);
148 print_num ("Generator", &g
);
149 print_num ("Prime", &n
);
151 if (gnutls_srp_base64_encode_alloc (&n
, &str_n
) < 0)
153 fprintf (stderr
, "Could not encode\n");
157 if (gnutls_srp_base64_encode_alloc (&g
, &str_g
) < 0)
159 fprintf (stderr
, "Could not encode\n");
163 sprintf (line
, "%d:%s:%s\n", index
, str_n
.data
, str_g
.data
);
165 gnutls_free (str_n
.data
);
166 gnutls_free (str_g
.data
);
168 fwrite (line
, 1, strlen (line
), fd
);
178 /* The format of a tpasswd file is:
179 * username:verifier:salt:index
181 * index is the index of the prime-generator pair in tpasswd.conf
184 _verify_passwd_int (const char *username
, const char *passwd
,
185 char *verifier
, char *salt
,
186 const gnutls_datum_t
* g
, const gnutls_datum_t
* n
)
189 gnutls_datum_t tmp
, raw_salt
, new_verifier
;
193 if (salt
== NULL
|| verifier
== NULL
)
196 /* copy salt, and null terminate after the ':' */
197 strcpy (_salt
, salt
);
198 pos
= strchr (_salt
, ':');
202 /* convert salt to binary. */
204 tmp
.size
= strlen (_salt
);
206 if (gnutls_srp_base64_decode_alloc (&tmp
, &raw_salt
) < 0)
208 fprintf (stderr
, "Could not decode salt.\n");
212 if (gnutls_srp_verifier
213 (username
, passwd
, &raw_salt
, g
, n
, &new_verifier
) < 0)
215 fprintf (stderr
, "Could not make the verifier\n");
219 free (raw_salt
.data
);
221 /* encode the verifier into _salt */
222 salt_size
= sizeof (_salt
);
223 if (gnutls_srp_base64_encode (&new_verifier
, _salt
, &salt_size
) < 0)
225 fprintf (stderr
, "Encoding error\n");
229 free (new_verifier
.data
);
231 if (strncmp (verifier
, _salt
, strlen (_salt
)) == 0)
233 fprintf (stderr
, "Password verified\n");
238 fprintf (stderr
, "Password does NOT match\n");
244 filecopy (char *src
, char *dst
)
250 fd
= fopen (dst
, "w");
253 fprintf (stderr
, "Cannot open '%s' for write\n", dst
);
257 fd2
= fopen (src
, "r");
265 line
[sizeof (line
) - 1] = 0;
268 p
= fgets (line
, sizeof (line
) - 1, fd2
);
282 /* accepts password file */
284 find_strchr (char *username
, char *file
)
291 fd
= fopen (file
, "r");
294 fprintf (stderr
, "Cannot open file '%s'\n", file
);
298 while (fgets (line
, sizeof (line
), fd
) != NULL
)
300 /* move to first ':' */
302 while ((line
[i
] != ':') && (line
[i
] != '\0') && (i
< sizeof (line
)))
306 if (strncmp (username
, line
, _MAX (i
, strlen (username
))) == 0)
309 pos
= strrchr (line
, ':');
320 /* Parses the tpasswd files, in order to verify the given
321 * username/password pair.
324 verify_passwd (char *conffile
, char *tpasswd
, char *username
,
334 iindex
= find_strchr (username
, tpasswd
);
337 fprintf (stderr
, "Cannot find '%s' in %s\n", username
, tpasswd
);
341 fd
= fopen (conffile
, "r");
344 fprintf (stderr
, "Cannot find %s\n", conffile
);
350 p
= fgets (line
, sizeof (line
) - 1, fd
);
352 while (p
!= NULL
&& atoi (p
) != iindex
);
356 fprintf (stderr
, "Cannot find entry in %s\n", conffile
);
359 line
[sizeof (line
) - 1] = 0;
363 if ((iindex
= read_conf_values (&g
, &n
, line
)) < 0)
365 fprintf (stderr
, "Cannot parse conf file '%s'\n", conffile
);
369 fd
= fopen (tpasswd
, "r");
372 fprintf (stderr
, "Cannot open file '%s'\n", tpasswd
);
376 while (fgets (line
, sizeof (line
), fd
) != NULL
)
379 * This is the actual verifier.
382 while ((line
[i
] != ':') && (line
[i
] != '\0') && (i
< sizeof (line
)))
386 if (strncmp (username
, line
, _MAX (i
, strlen (username
))) == 0)
388 char *verifier_pos
, *salt_pos
;
390 pos
= strchr (line
, ':');
394 fprintf (stderr
, "Cannot parse conf file '%s'\n", conffile
);
400 /* Move to the salt */
401 pos
= strchr (pos
, ':');
404 fprintf (stderr
, "Cannot parse conf file '%s'\n", conffile
);
410 return _verify_passwd_int (username
, passwd
,
411 verifier_pos
, salt_pos
, &g
, &n
);
420 #define KPASSWD "/etc/tpasswd"
421 #define KPASSWD_CONF "/etc/tpasswd.conf"
424 main (int argc
, char **argv
)
431 if ((ret
= gnutls_global_init ()) < 0)
433 fprintf (stderr
, "global_init: %s\n", gnutls_strerror (ret
));
441 if (gaa (argc
, argv
, &info
) != -1)
443 fprintf (stderr
, "Error in the arguments.\n");
449 if (info
.create_conf
!= NULL
)
451 return generate_create_conf (info
.create_conf
);
454 if (info
.passwd
== NULL
)
455 info
.passwd
= KPASSWD
;
456 if (info
.passwd_conf
== NULL
)
457 info
.passwd_conf
= KPASSWD_CONF
;
459 if (info
.username
== NULL
)
462 pwd
= getpwuid (getuid ());
466 fprintf (stderr
, "No such user\n");
470 info
.username
= pwd
->pw_name
;
472 fprintf (stderr
, "Please specify a user\n");
479 passwd
= getpass ("Enter password: ");
482 fprintf (stderr
, "Please specify a password\n");
487 if (info
.verify
!= 0)
489 return verify_passwd (info
.passwd_conf
, info
.passwd
,
490 info
.username
, passwd
);
494 return crypt_int (info
.username
, passwd
, salt
,
495 info
.passwd_conf
, info
.passwd
, info
.index
);
500 _srp_crypt (const char *username
, const char *passwd
, int salt_size
,
501 const gnutls_datum_t
* g
, const gnutls_datum_t
* n
)
504 static char result
[1024];
505 gnutls_datum_t dat_salt
, txt_salt
;
506 gnutls_datum_t verifier
, txt_verifier
;
508 if ((unsigned) salt_size
> sizeof (salt
))
513 if (gc_nonce (salt
, salt_size
) != GC_OK
)
515 fprintf (stderr
, "Could not create nonce\n");
519 dat_salt
.data
= salt
;
520 dat_salt
.size
= salt_size
;
522 if (gnutls_srp_verifier (username
, passwd
, &dat_salt
, g
, n
, &verifier
) < 0)
524 fprintf (stderr
, "Error getting verifier\n");
528 /* base64 encode the verifier */
529 if (gnutls_srp_base64_encode_alloc (&verifier
, &txt_verifier
) < 0)
531 fprintf (stderr
, "Error encoding\n");
532 free (verifier
.data
);
536 free (verifier
.data
);
538 if (gnutls_srp_base64_encode_alloc (&dat_salt
, &txt_salt
) < 0)
540 fprintf (stderr
, "Error encoding\n");
544 sprintf (result
, "%s:%s", txt_verifier
.data
, txt_salt
.data
);
545 free (txt_salt
.data
);
546 free (txt_verifier
.data
);
554 crypt_int (const char *username
, const char *passwd
, int salt_size
,
555 char *tpasswd_conf
, char *tpasswd
, int uindex
)
565 fd
= fopen (tpasswd_conf
, "r");
568 fprintf (stderr
, "Cannot find %s\n", tpasswd_conf
);
573 { /* find the specified uindex in file */
574 p
= fgets (line
, sizeof (line
) - 1, fd
);
577 while (p
!= NULL
&& iindex
!= uindex
);
581 fprintf (stderr
, "Cannot find entry in %s\n", tpasswd_conf
);
584 line
[sizeof (line
) - 1] = 0;
587 if ((iindex
= read_conf_values (&g
, &n
, line
)) < 0)
589 fprintf (stderr
, "Cannot parse conf file '%s'\n", tpasswd_conf
);
593 cr
= _srp_crypt (username
, passwd
, salt_size
, &g
, &n
);
596 fprintf (stderr
, "Cannot _srp_crypt()...\n");
601 /* delete previous entry */
606 if (strlen (tpasswd
) > sizeof (tmpname
) + 5)
608 fprintf (stderr
, "file '%s' is tooooo long\n", tpasswd
);
611 strcpy (tmpname
, tpasswd
);
612 strcat (tmpname
, ".tmp");
614 if (stat (tmpname
, &st
) != -1)
616 fprintf (stderr
, "file '%s' is locked\n", tpasswd
);
620 if (filecopy (tpasswd
, tmpname
) != 0)
622 fprintf (stderr
, "Cannot copy '%s' to '%s'\n", tpasswd
, tmpname
);
626 fd
= fopen (tpasswd
, "w");
629 fprintf (stderr
, "Cannot open '%s' for write\n", tpasswd
);
634 fd2
= fopen (tmpname
, "r");
637 fprintf (stderr
, "Cannot open '%s' for read\n", tmpname
);
645 p
= fgets (line
, sizeof (line
) - 1, fd2
);
649 pp
= strchr (line
, ':');
655 _MAX (strlen (username
), (unsigned int) (pp
- p
))) == 0)
658 fprintf (fd
, "%s:%s:%u\n", username
, cr
, iindex
);
669 fprintf (fd
, "%s:%s:%u\n", username
, cr
, iindex
);
685 /* this function parses tpasswd.conf file. Format is:
686 * int(index):base64(n):base64(g)
689 read_conf_values (gnutls_datum_t
* g
, gnutls_datum_t
* n
, char *str
)
698 p
= strrchr (str
, ':'); /* we have g */
707 /* read the generator */
709 if (p
[len
- 1] == '\n')
714 ret
= gnutls_srp_base64_decode_alloc (&dat
, g
);
718 fprintf (stderr
, "Decoding error\n");
722 /* now go for n - modulo */
723 p
= strrchr (str
, ':'); /* we have n */
733 dat
.size
= strlen (p
);
735 ret
= gnutls_srp_base64_decode_alloc (&dat
, n
);
739 fprintf (stderr
, "Decoding error\n");
747 #endif /* ENABLE_SRP */