2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
4 * This file is part of GnuTLS.
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.
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.
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/>.
26 #include <gnutls/gnutls.h>
27 #include <gnutls/crypto.h> /* for random */
29 #include <sys/types.h>
39 /* Gnulib portability files. */
43 #include <version-etc.h>
46 #include <srptool-args.h>
48 /* This may need some rewrite. A lot of stuff which should be here
49 * are in the library, which is not good.
52 int crypt_int (const char *username
, const char *passwd
, int salt
,
53 const char *tpasswd_conf
, const char *tpasswd
, int uindex
);
54 static int read_conf_values (gnutls_datum_t
* g
, gnutls_datum_t
* n
,
56 static int _verify_passwd_int (const char *username
, const char *passwd
,
57 char *verifier
, const char *salt
,
58 const gnutls_datum_t
* g
,
59 const gnutls_datum_t
* n
);
62 print_num (const char *msg
, const gnutls_datum_t
* num
)
66 printf ("%s:\t", msg
);
68 for (i
= 0; i
< num
->size
; i
++)
70 if (i
!= 0 && i
% 12 == 0)
72 else if (i
!= 0 && i
!= num
->size
)
74 printf ("%.2x", num
->data
[i
]);
81 generate_create_conf (const char *tpasswd_conf
)
87 gnutls_datum_t str_g
, str_n
;
89 fd
= fopen (tpasswd_conf
, "w");
92 fprintf (stderr
, "Cannot open file '%s'\n", tpasswd_conf
);
96 for (index
= 1; index
<= 5; index
++)
101 n
= gnutls_srp_1024_group_prime
;
102 g
= gnutls_srp_1024_group_generator
;
106 n
= gnutls_srp_1536_group_prime
;
107 g
= gnutls_srp_1536_group_generator
;
111 n
= gnutls_srp_2048_group_prime
;
112 g
= gnutls_srp_2048_group_generator
;
116 n
= gnutls_srp_3072_group_prime
;
117 g
= gnutls_srp_3072_group_generator
;
121 n
= gnutls_srp_4096_group_prime
;
122 g
= gnutls_srp_4096_group_generator
;
126 fprintf(stderr
, "Unknown index: %d\n", index
);
130 printf ("\nGroup %d, of %d bits:\n", index
, n
.size
* 8);
131 print_num ("Generator", &g
);
132 print_num ("Prime", &n
);
134 if (gnutls_srp_base64_encode_alloc (&n
, &str_n
) < 0)
136 fprintf (stderr
, "Could not encode\n");
140 if (gnutls_srp_base64_encode_alloc (&g
, &str_g
) < 0)
142 fprintf (stderr
, "Could not encode\n");
146 sprintf (line
, "%d:%s:%s\n", index
, str_n
.data
, str_g
.data
);
148 gnutls_free (str_n
.data
);
149 gnutls_free (str_g
.data
);
151 fwrite (line
, 1, strlen (line
), fd
);
161 /* The format of a tpasswd file is:
162 * username:verifier:salt:index
164 * index is the index of the prime-generator pair in tpasswd.conf
167 _verify_passwd_int (const char *username
, const char *passwd
,
168 char *verifier
, const char *salt
,
169 const gnutls_datum_t
* g
, const gnutls_datum_t
* n
)
172 gnutls_datum_t tmp
, raw_salt
, new_verifier
;
176 if (salt
== NULL
|| verifier
== NULL
)
179 if (strlen(salt
) >= sizeof(_salt
))
181 fprintf (stderr
, "Too long salt.\n");
185 /* copy salt, and null terminate after the ':' */
186 strcpy (_salt
, salt
);
187 pos
= strchr (_salt
, ':');
191 /* convert salt to binary. */
192 tmp
.data
= (void*)_salt
;
193 tmp
.size
= strlen (_salt
);
195 if (gnutls_srp_base64_decode_alloc (&tmp
, &raw_salt
) < 0)
197 fprintf (stderr
, "Could not decode salt.\n");
201 if (gnutls_srp_verifier
202 (username
, passwd
, &raw_salt
, g
, n
, &new_verifier
) < 0)
204 fprintf (stderr
, "Could not make the verifier\n");
208 free (raw_salt
.data
);
210 /* encode the verifier into _salt */
211 salt_size
= sizeof (_salt
);
212 memset (_salt
, 0, salt_size
);
213 if (gnutls_srp_base64_encode (&new_verifier
, _salt
, &salt_size
) < 0)
215 fprintf (stderr
, "Encoding error\n");
219 free (new_verifier
.data
);
221 if (strncmp (verifier
, _salt
, strlen (_salt
)) == 0)
223 fprintf (stderr
, "Password verified\n");
228 fprintf (stderr
, "Password does NOT match\n");
234 filecopy (const char *src
, const char *dst
)
240 fd
= fopen (dst
, "w");
243 fprintf (stderr
, "Cannot open '%s' for write\n", dst
);
247 fd2
= fopen (src
, "r");
255 line
[sizeof (line
) - 1] = 0;
258 p
= fgets (line
, sizeof (line
) - 1, fd2
);
272 /* accepts password file */
274 find_strchr (const char *username
, const char *file
)
281 fd
= fopen (file
, "r");
284 fprintf (stderr
, "Cannot open file '%s'\n", file
);
288 while (fgets (line
, sizeof (line
), fd
) != NULL
)
290 /* move to first ':' */
292 while ((line
[i
] != ':') && (line
[i
] != '\0') && (i
< sizeof (line
)))
296 if (strncmp (username
, line
, MAX (i
, strlen (username
))) == 0)
299 pos
= strrchr (line
, ':');
310 /* Parses the tpasswd files, in order to verify the given
311 * username/password pair.
314 verify_passwd (const char *conffile
, const char *tpasswd
,
315 const char *username
, const char *passwd
)
324 iindex
= find_strchr (username
, tpasswd
);
327 fprintf (stderr
, "Cannot find '%s' in %s\n", username
, tpasswd
);
331 fd
= fopen (conffile
, "r");
334 fprintf (stderr
, "Cannot find %s\n", conffile
);
340 p
= fgets (line
, sizeof (line
) - 1, fd
);
342 while (p
!= NULL
&& atoi (p
) != iindex
);
346 fprintf (stderr
, "Cannot find entry in %s\n", conffile
);
349 line
[sizeof (line
) - 1] = 0;
353 if ((iindex
= read_conf_values (&g
, &n
, line
)) < 0)
355 fprintf (stderr
, "Cannot parse conf file '%s'\n", conffile
);
359 fd
= fopen (tpasswd
, "r");
362 fprintf (stderr
, "Cannot open file '%s'\n", tpasswd
);
366 while (fgets (line
, sizeof (line
), fd
) != NULL
)
369 * This is the actual verifier.
372 while ((line
[i
] != ':') && (line
[i
] != '\0') && (i
< sizeof (line
)))
376 if (strncmp (username
, line
, MAX (i
, strlen (username
))) == 0)
378 char *verifier_pos
, *salt_pos
;
380 pos
= strchr (line
, ':');
384 fprintf (stderr
, "Cannot parse conf file '%s'\n", conffile
);
390 /* Move to the salt */
391 pos
= strchr (pos
, ':');
394 fprintf (stderr
, "Cannot parse conf file '%s'\n", conffile
);
400 return _verify_passwd_int (username
, passwd
,
401 verifier_pos
, salt_pos
, &g
, &n
);
410 #define KPASSWD "/etc/tpasswd"
411 #define KPASSWD_CONF "/etc/tpasswd.conf"
414 tls_log_func (int level
, const char *str
)
416 fprintf (stderr
, "|<%d>| %s", level
, str
);
419 int main (int argc
, char **argv
)
424 const char* fpasswd
, *fpasswd_conf
;
425 const char* username
;
430 set_program_name (argv
[0]);
432 if ((ret
= gnutls_global_init ()) < 0)
434 fprintf (stderr
, "global_init: %s\n", gnutls_strerror (ret
));
440 optct
= optionProcess( &srptoolOptions
, argc
, argv
);
444 gnutls_global_set_log_function (tls_log_func
);
445 gnutls_global_set_log_level (OPT_VALUE_DEBUG
);
447 if (HAVE_OPT(CREATE_CONF
))
449 return generate_create_conf (OPT_ARG(CREATE_CONF
));
452 if (HAVE_OPT(PASSWD
))
453 fpasswd
= OPT_ARG(PASSWD
);
455 fpasswd
= (char *) KPASSWD
;
457 if (HAVE_OPT(PASSWD_CONF
))
458 fpasswd_conf
= OPT_ARG(PASSWD_CONF
);
460 fpasswd_conf
= (char *) KPASSWD_CONF
;
462 if (HAVE_OPT(USERNAME
))
463 username
= OPT_ARG(USERNAME
);
467 pwd
= getpwuid (getuid ());
471 fprintf (stderr
, "No such user\n");
475 username
= pwd
->pw_name
;
477 fprintf (stderr
, "Please specify a user\n");
484 passwd
= getpass ("Enter password: ");
487 fprintf (stderr
, "Please specify a password\n");
492 if (HAVE_OPT(VERIFY
))
494 return verify_passwd (fpasswd_conf
, fpasswd
,
499 return crypt_int (username
, passwd
, salt_size
,
500 fpasswd_conf
, fpasswd
, VALUE_OPT_INDEX
);
505 _srp_crypt (const char *username
, const char *passwd
, int salt_size
,
506 const gnutls_datum_t
* g
, const gnutls_datum_t
* n
)
508 unsigned char salt
[128];
509 static char result
[1024];
510 gnutls_datum_t dat_salt
, txt_salt
;
511 gnutls_datum_t verifier
, txt_verifier
;
513 if ((unsigned) salt_size
> sizeof (salt
))
518 if (gnutls_rnd (GNUTLS_RND_NONCE
, salt
, salt_size
) < 0)
520 fprintf (stderr
, "Could not create nonce\n");
524 dat_salt
.data
= salt
;
525 dat_salt
.size
= salt_size
;
527 if (gnutls_srp_verifier (username
, passwd
, &dat_salt
, g
, n
, &verifier
) < 0)
529 fprintf (stderr
, "Error getting verifier\n");
533 /* base64 encode the verifier */
534 if (gnutls_srp_base64_encode_alloc (&verifier
, &txt_verifier
) < 0)
536 fprintf (stderr
, "Error encoding\n");
537 free (verifier
.data
);
541 free (verifier
.data
);
543 if (gnutls_srp_base64_encode_alloc (&dat_salt
, &txt_salt
) < 0)
545 fprintf (stderr
, "Error encoding\n");
549 sprintf (result
, "%s:%s", txt_verifier
.data
, txt_salt
.data
);
550 free (txt_salt
.data
);
551 free (txt_verifier
.data
);
559 crypt_int (const char *username
, const char *passwd
, int salt_size
,
560 const char *tpasswd_conf
, const char *tpasswd
, int uindex
)
570 fd
= fopen (tpasswd_conf
, "r");
573 fprintf (stderr
, "Cannot find %s\n", tpasswd_conf
);
578 { /* find the specified uindex in file */
579 p
= fgets (line
, sizeof (line
) - 1, fd
);
582 while (p
!= NULL
&& iindex
!= uindex
);
586 fprintf (stderr
, "Cannot find entry in %s\n", tpasswd_conf
);
589 line
[sizeof (line
) - 1] = 0;
592 if ((iindex
= read_conf_values (&g
, &n
, line
)) < 0)
594 fprintf (stderr
, "Cannot parse conf file '%s'\n", tpasswd_conf
);
598 cr
= _srp_crypt (username
, passwd
, salt_size
, &g
, &n
);
601 fprintf (stderr
, "Cannot _srp_crypt()...\n");
606 /* delete previous entry */
611 if (strlen (tpasswd
) > sizeof (tmpname
) + 5)
613 fprintf (stderr
, "file '%s' is tooooo long\n", tpasswd
);
616 strcpy (tmpname
, tpasswd
);
617 strcat (tmpname
, ".tmp");
619 if (stat (tmpname
, &st
) != -1)
621 fprintf (stderr
, "file '%s' is locked\n", tpasswd
);
625 if (filecopy (tpasswd
, tmpname
) != 0)
627 fprintf (stderr
, "Cannot copy '%s' to '%s'\n", tpasswd
, tmpname
);
631 fd
= fopen (tpasswd
, "w");
634 fprintf (stderr
, "Cannot open '%s' for write\n", tpasswd
);
639 fd2
= fopen (tmpname
, "r");
642 fprintf (stderr
, "Cannot open '%s' for read\n", tmpname
);
650 p
= fgets (line
, sizeof (line
) - 1, fd2
);
654 pp
= strchr (line
, ':');
658 if (strncmp (p
, username
,
659 MAX (strlen (username
), (unsigned int) (pp
- p
))) == 0)
662 fprintf (fd
, "%s:%s:%u\n", username
, cr
, iindex
);
673 fprintf (fd
, "%s:%s:%u\n", username
, cr
, iindex
);
689 /* this function parses tpasswd.conf file. Format is:
690 * int(index):base64(n):base64(g)
693 read_conf_values (gnutls_datum_t
* g
, gnutls_datum_t
* n
, char *str
)
702 p
= strrchr (str
, ':'); /* we have g */
711 /* read the generator */
713 if (p
[len
- 1] == '\n')
718 ret
= gnutls_srp_base64_decode_alloc (&dat
, g
);
722 fprintf (stderr
, "Decoding error\n");
726 /* now go for n - modulo */
727 p
= strrchr (str
, ':'); /* we have n */
737 dat
.size
= strlen (p
);
739 ret
= gnutls_srp_base64_decode_alloc (&dat
, n
);
743 fprintf (stderr
, "Decoding error\n");
751 extern void srptool_version (void);
754 srptool_version (void)
756 const char *p
= PACKAGE_NAME
;
757 if (strcmp (gnutls_check_version (NULL
), PACKAGE_VERSION
) != 0)
759 version_etc (stdout
, "srptool", p
, gnutls_check_version (NULL
),
760 "Nikos Mavrogiannopoulos", (char *) NULL
);