2 * Copyright (C) 2004, 2005, 2006, 2007 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
));
440 if (gaa (argc
, argv
, &info
) != -1)
442 fprintf (stderr
, "Error in the arguments.\n");
448 if (info
.create_conf
!= NULL
)
450 return generate_create_conf (info
.create_conf
);
453 if (info
.passwd
== NULL
)
454 info
.passwd
= KPASSWD
;
455 if (info
.passwd_conf
== NULL
)
456 info
.passwd_conf
= KPASSWD_CONF
;
458 if (info
.username
== NULL
)
461 pwd
= getpwuid (getuid ());
465 fprintf (stderr
, "No such user\n");
469 info
.username
= pwd
->pw_name
;
471 fprintf (stderr
, "Please specify a user\n");
478 passwd
= getpass ("Enter password: ");
481 fprintf (stderr
, "Please specify a password\n");
486 if (info
.verify
!= 0)
488 return verify_passwd (info
.passwd_conf
, info
.passwd
,
489 info
.username
, passwd
);
493 return crypt_int (info
.username
, passwd
, salt
,
494 info
.passwd_conf
, info
.passwd
, info
.index
);
499 _srp_crypt (const char *username
, const char *passwd
, int salt_size
,
500 const gnutls_datum_t
* g
, const gnutls_datum_t
* n
)
503 static char result
[1024];
504 gnutls_datum_t dat_salt
, txt_salt
;
505 gnutls_datum_t verifier
, txt_verifier
;
507 if ((unsigned) salt_size
> sizeof (salt
))
512 if (gc_nonce (salt
, salt_size
) != GC_OK
)
514 fprintf (stderr
, "Could not create nonce\n");
518 dat_salt
.data
= salt
;
519 dat_salt
.size
= salt_size
;
521 if (gnutls_srp_verifier (username
, passwd
, &dat_salt
, g
, n
, &verifier
) < 0)
523 fprintf (stderr
, "Error getting verifier\n");
527 /* base64 encode the verifier */
528 if (gnutls_srp_base64_encode_alloc (&verifier
, &txt_verifier
) < 0)
530 fprintf (stderr
, "Error encoding\n");
531 free (verifier
.data
);
535 free (verifier
.data
);
537 if (gnutls_srp_base64_encode_alloc (&dat_salt
, &txt_salt
) < 0)
539 fprintf (stderr
, "Error encoding\n");
543 sprintf (result
, "%s:%s", txt_verifier
.data
, txt_salt
.data
);
544 free (txt_salt
.data
);
545 free (txt_verifier
.data
);
553 crypt_int (const char *username
, const char *passwd
, int salt_size
,
554 char *tpasswd_conf
, char *tpasswd
, int uindex
)
564 fd
= fopen (tpasswd_conf
, "r");
567 fprintf (stderr
, "Cannot find %s\n", tpasswd_conf
);
572 { /* find the specified uindex in file */
573 p
= fgets (line
, sizeof (line
) - 1, fd
);
576 while (p
!= NULL
&& iindex
!= uindex
);
580 fprintf (stderr
, "Cannot find entry in %s\n", tpasswd_conf
);
583 line
[sizeof (line
) - 1] = 0;
586 if ((iindex
= read_conf_values (&g
, &n
, line
)) < 0)
588 fprintf (stderr
, "Cannot parse conf file '%s'\n", tpasswd_conf
);
592 cr
= _srp_crypt (username
, passwd
, salt_size
, &g
, &n
);
595 fprintf (stderr
, "Cannot _srp_crypt()...\n");
600 /* delete previous entry */
605 if (strlen (tpasswd
) > sizeof (tmpname
) + 5)
607 fprintf (stderr
, "file '%s' is tooooo long\n", tpasswd
);
610 strcpy (tmpname
, tpasswd
);
611 strcat (tmpname
, ".tmp");
613 if (stat (tmpname
, &st
) != -1)
615 fprintf (stderr
, "file '%s' is locked\n", tpasswd
);
619 if (filecopy (tpasswd
, tmpname
) != 0)
621 fprintf (stderr
, "Cannot copy '%s' to '%s'\n", tpasswd
, tmpname
);
625 fd
= fopen (tpasswd
, "w");
628 fprintf (stderr
, "Cannot open '%s' for write\n", tpasswd
);
633 fd2
= fopen (tmpname
, "r");
636 fprintf (stderr
, "Cannot open '%s' for read\n", tmpname
);
644 p
= fgets (line
, sizeof (line
) - 1, fd2
);
648 pp
= strchr (line
, ':');
654 _MAX (strlen (username
), (unsigned int) (pp
- p
))) == 0)
657 fprintf (fd
, "%s:%s:%u\n", username
, cr
, iindex
);
668 fprintf (fd
, "%s:%s:%u\n", username
, cr
, iindex
);
684 /* this function parses tpasswd.conf file. Format is:
685 * int(index):base64(n):base64(g)
688 read_conf_values (gnutls_datum_t
* g
, gnutls_datum_t
* n
, char *str
)
697 p
= strrchr (str
, ':'); /* we have g */
706 /* read the generator */
708 if (p
[len
- 1] == '\n')
713 ret
= gnutls_srp_base64_decode_alloc (&dat
, g
);
717 fprintf (stderr
, "Decoding error\n");
721 /* now go for n - modulo */
722 p
= strrchr (str
, ':'); /* we have n */
732 dat
.size
= strlen (p
);
734 ret
= gnutls_srp_base64_decode_alloc (&dat
, n
);
738 fprintf (stderr
, "Decoding error\n");
746 #endif /* ENABLE_SRP */