Fix dangling/unused bindings in `(gnutls)'.
[gnutls.git] / src / crypt.c
blob9058381c47897a0b2483be8b477084a13d21779c
1 /*
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/>.
22 #include <config.h>
26 #ifndef ENABLE_SRP
28 #include <stdio.h>
30 int
31 main (int argc, char **argv)
33 printf ("\nSRP not supported. This program is a dummy.\n\n");
34 return 1;
37 void
38 srptool_version (void)
40 fprintf (stderr, "GNU TLS dummy srptool.\n");
43 #else
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdlib.h>
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>
55 #include <sys/stat.h>
57 #ifndef _WIN32
58 # include <pwd.h>
59 # include <unistd.h>
60 #else
61 # include <windows.h>
62 #endif
64 /* Gnulib portability files. */
65 #include <getpass.h>
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);
81 void
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);
92 static void
93 print_num (const char *msg, const gnutls_datum_t * num)
95 unsigned int i;
97 printf ("%s:\t", msg);
99 for (i = 0; i < num->size; i++)
101 if (i != 0 && i % 12 == 0)
102 printf ("\n\t");
103 else if (i != 0 && i != num->size)
104 printf (":");
105 printf ("%.2x", num->data[i]);
107 printf ("\n\n");
112 generate_create_conf (char *tpasswd_conf)
114 FILE *fd;
115 char line[5 * 1024];
116 int index = 1;
117 gnutls_datum_t g, n;
118 gnutls_datum_t str_g, str_n;
120 fd = fopen (tpasswd_conf, "w");
121 if (fd == NULL)
123 fprintf (stderr, "Cannot open file '%s'\n", tpasswd_conf);
124 return -1;
127 for (index = 1; index <= 3; index++)
130 if (index == 1)
132 n = gnutls_srp_1024_group_prime;
133 g = gnutls_srp_1024_group_generator;
135 else if (index == 2)
137 n = gnutls_srp_1536_group_prime;
138 g = gnutls_srp_1536_group_generator;
140 else
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");
153 return -1;
156 if (gnutls_srp_base64_encode_alloc (&g, &str_g) < 0)
158 fprintf (stderr, "Could not encode\n");
159 return -1;
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);
171 fclose (fd);
173 return 0;
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
182 static int
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)
187 char _salt[1024];
188 gnutls_datum_t tmp, raw_salt, new_verifier;
189 size_t salt_size;
190 char *pos;
192 if (salt == NULL || verifier == NULL)
193 return -1;
195 /* copy salt, and null terminate after the ':' */
196 strcpy (_salt, salt);
197 pos = strchr (_salt, ':');
198 if (pos != NULL)
199 *pos = 0;
201 /* convert salt to binary. */
202 tmp.data = _salt;
203 tmp.size = strlen (_salt);
205 if (gnutls_srp_base64_decode_alloc (&tmp, &raw_salt) < 0)
207 fprintf (stderr, "Could not decode salt.\n");
208 return -1;
211 if (gnutls_srp_verifier
212 (username, passwd, &raw_salt, g, n, &new_verifier) < 0)
214 fprintf (stderr, "Could not make the verifier\n");
215 return -1;
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");
225 return -1;
228 free (new_verifier.data);
230 if (strncmp (verifier, _salt, strlen (_salt)) == 0)
232 fprintf (stderr, "Password verified\n");
233 return 0;
235 else
237 fprintf (stderr, "Password does NOT match\n");
239 return -1;
242 static int
243 filecopy (char *src, char *dst)
245 FILE *fd, *fd2;
246 char line[5 * 1024];
247 char *p;
249 fd = fopen (dst, "w");
250 if (fd == NULL)
252 fprintf (stderr, "Cannot open '%s' for write\n", dst);
253 return -1;
256 fd2 = fopen (src, "r");
257 if (fd2 == NULL)
259 /* empty file */
260 fclose (fd);
261 return 0;
264 line[sizeof (line) - 1] = 0;
267 p = fgets (line, sizeof (line) - 1, fd2);
268 if (p == NULL)
269 break;
271 fputs (line, fd);
273 while (1);
275 fclose (fd);
276 fclose (fd2);
278 return 0;
281 /* accepts password file */
282 static int
283 find_strchr (char *username, char *file)
285 FILE *fd;
286 char *pos;
287 char line[5 * 1024];
288 unsigned int i;
290 fd = fopen (file, "r");
291 if (fd == NULL)
293 fprintf (stderr, "Cannot open file '%s'\n", file);
294 return -1;
297 while (fgets (line, sizeof (line), fd) != NULL)
299 /* move to first ':' */
300 i = 0;
301 while ((line[i] != ':') && (line[i] != '\0') && (i < sizeof (line)))
303 i++;
305 if (strncmp (username, line, _MAX (i, strlen (username))) == 0)
307 /* find the index */
308 pos = strrchr (line, ':');
309 pos++;
310 fclose (fd);
311 return atoi (pos);
315 fclose (fd);
316 return -1;
319 /* Parses the tpasswd files, in order to verify the given
320 * username/password pair.
323 verify_passwd (char *conffile, char *tpasswd, char *username,
324 const char *passwd)
326 FILE *fd;
327 char line[5 * 1024];
328 unsigned int i;
329 gnutls_datum_t g, n;
330 int iindex;
331 char *p, *pos;
333 iindex = find_strchr (username, tpasswd);
334 if (iindex == -1)
336 fprintf (stderr, "Cannot find '%s' in %s\n", username, tpasswd);
337 return -1;
340 fd = fopen (conffile, "r");
341 if (fd == NULL)
343 fprintf (stderr, "Cannot find %s\n", conffile);
344 return -1;
349 p = fgets (line, sizeof (line) - 1, fd);
351 while (p != NULL && atoi (p) != iindex);
353 if (p == NULL)
355 fprintf (stderr, "Cannot find entry in %s\n", conffile);
356 return -1;
358 line[sizeof (line) - 1] = 0;
360 fclose (fd);
362 if ((iindex = read_conf_values (&g, &n, line)) < 0)
364 fprintf (stderr, "Cannot parse conf file '%s'\n", conffile);
365 return -1;
368 fd = fopen (tpasswd, "r");
369 if (fd == NULL)
371 fprintf (stderr, "Cannot open file '%s'\n", tpasswd);
372 return -1;
375 while (fgets (line, sizeof (line), fd) != NULL)
377 /* move to first ':'
378 * This is the actual verifier.
380 i = 0;
381 while ((line[i] != ':') && (line[i] != '\0') && (i < sizeof (line)))
383 i++;
385 if (strncmp (username, line, _MAX (i, strlen (username))) == 0)
387 char *verifier_pos, *salt_pos;
389 pos = strchr (line, ':');
390 fclose (fd);
391 if (pos == NULL)
393 fprintf (stderr, "Cannot parse conf file '%s'\n", conffile);
394 return -1;
396 pos++;
397 verifier_pos = pos;
399 /* Move to the salt */
400 pos = strchr (pos, ':');
401 if (pos == NULL)
403 fprintf (stderr, "Cannot parse conf file '%s'\n", conffile);
404 return -1;
406 pos++;
407 salt_pos = pos;
409 return _verify_passwd_int (username, passwd,
410 verifier_pos, salt_pos, &g, &n);
414 fclose (fd);
415 return -1;
419 #define KPASSWD "/etc/tpasswd"
420 #define KPASSWD_CONF "/etc/tpasswd.conf"
423 main (int argc, char **argv)
425 gaainfo info;
426 const char *passwd;
427 int salt, ret;
428 struct passwd *pwd;
430 if ((ret = gnutls_global_init ()) < 0)
432 fprintf (stderr, "global_init: %s\n", gnutls_strerror (ret));
433 exit (1);
436 #ifdef HAVE_UMASK
437 umask (066);
438 #endif
440 if (gaa (argc, argv, &info) != -1)
442 fprintf (stderr, "Error in the arguments.\n");
443 return -1;
446 salt = info.salt;
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)
460 #ifndef _WIN32
461 pwd = getpwuid (getuid ());
463 if (pwd == NULL)
465 fprintf (stderr, "No such user\n");
466 return -1;
469 info.username = pwd->pw_name;
470 #else
471 fprintf (stderr, "Please specify a user\n");
472 return -1;
473 #endif
476 salt = 16;
478 passwd = getpass ("Enter password: ");
479 if (passwd == NULL)
481 fprintf (stderr, "Please specify a password\n");
482 return -1;
485 /* not ready yet */
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);
498 char *
499 _srp_crypt (const char *username, const char *passwd, int salt_size,
500 const gnutls_datum_t * g, const gnutls_datum_t * n)
502 char salt[128];
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))
508 return NULL;
510 /* generate the salt
512 if (gc_nonce (salt, salt_size) != GC_OK)
514 fprintf (stderr, "Could not create nonce\n");
515 return NULL;
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");
524 return NULL;
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);
532 return NULL;
535 free (verifier.data);
537 if (gnutls_srp_base64_encode_alloc (&dat_salt, &txt_salt) < 0)
539 fprintf (stderr, "Error encoding\n");
540 return NULL;
543 sprintf (result, "%s:%s", txt_verifier.data, txt_salt.data);
544 free (txt_salt.data);
545 free (txt_verifier.data);
547 return result;
553 crypt_int (const char *username, const char *passwd, int salt_size,
554 char *tpasswd_conf, char *tpasswd, int uindex)
556 FILE *fd;
557 char *cr;
558 gnutls_datum_t g, n;
559 char line[5 * 1024];
560 char *p, *pp;
561 int iindex;
562 char tmpname[1024];
564 fd = fopen (tpasswd_conf, "r");
565 if (fd == NULL)
567 fprintf (stderr, "Cannot find %s\n", tpasswd_conf);
568 return -1;
572 { /* find the specified uindex in file */
573 p = fgets (line, sizeof (line) - 1, fd);
574 iindex = atoi (p);
576 while (p != NULL && iindex != uindex);
578 if (p == NULL)
580 fprintf (stderr, "Cannot find entry in %s\n", tpasswd_conf);
581 return -1;
583 line[sizeof (line) - 1] = 0;
585 fclose (fd);
586 if ((iindex = read_conf_values (&g, &n, line)) < 0)
588 fprintf (stderr, "Cannot parse conf file '%s'\n", tpasswd_conf);
589 return -1;
592 cr = _srp_crypt (username, passwd, salt_size, &g, &n);
593 if (cr == NULL)
595 fprintf (stderr, "Cannot _srp_crypt()...\n");
596 return -1;
598 else
600 /* delete previous entry */
601 struct stat st;
602 FILE *fd2;
603 int put;
605 if (strlen (tpasswd) > sizeof (tmpname) + 5)
607 fprintf (stderr, "file '%s' is tooooo long\n", tpasswd);
608 return -1;
610 strcpy (tmpname, tpasswd);
611 strcat (tmpname, ".tmp");
613 if (stat (tmpname, &st) != -1)
615 fprintf (stderr, "file '%s' is locked\n", tpasswd);
616 return -1;
619 if (filecopy (tpasswd, tmpname) != 0)
621 fprintf (stderr, "Cannot copy '%s' to '%s'\n", tpasswd, tmpname);
622 return -1;
625 fd = fopen (tpasswd, "w");
626 if (fd == NULL)
628 fprintf (stderr, "Cannot open '%s' for write\n", tpasswd);
629 remove (tmpname);
630 return -1;
633 fd2 = fopen (tmpname, "r");
634 if (fd2 == NULL)
636 fprintf (stderr, "Cannot open '%s' for read\n", tmpname);
637 remove (tmpname);
638 return -1;
641 put = 0;
644 p = fgets (line, sizeof (line) - 1, fd2);
645 if (p == NULL)
646 break;
648 pp = strchr (line, ':');
649 if (pp == NULL)
650 continue;
652 if (strncmp
653 (p, username,
654 _MAX (strlen (username), (unsigned int) (pp - p))) == 0)
656 put = 1;
657 fprintf (fd, "%s:%s:%u\n", username, cr, iindex);
659 else
661 fputs (line, fd);
664 while (1);
666 if (put == 0)
668 fprintf (fd, "%s:%s:%u\n", username, cr, iindex);
671 fclose (fd);
672 fclose (fd2);
674 remove (tmpname);
679 return 0;
684 /* this function parses tpasswd.conf file. Format is:
685 * int(index):base64(n):base64(g)
687 static int
688 read_conf_values (gnutls_datum_t * g, gnutls_datum_t * n, char *str)
690 char *p;
691 int len;
692 int index, ret;
693 gnutls_datum_t dat;
695 index = atoi (str);
697 p = strrchr (str, ':'); /* we have g */
698 if (p == NULL)
700 return -1;
703 *p = '\0';
704 p++;
706 /* read the generator */
707 len = strlen (p);
708 if (p[len - 1] == '\n')
709 len--;
711 dat.data = p;
712 dat.size = len;
713 ret = gnutls_srp_base64_decode_alloc (&dat, g);
715 if (ret < 0)
717 fprintf (stderr, "Decoding error\n");
718 return -1;
721 /* now go for n - modulo */
722 p = strrchr (str, ':'); /* we have n */
723 if (p == NULL)
725 return -1;
728 *p = '\0';
729 p++;
731 dat.data = p;
732 dat.size = strlen (p);
734 ret = gnutls_srp_base64_decode_alloc (&dat, n);
736 if (ret < 0)
738 fprintf (stderr, "Decoding error\n");
739 free (g->data);
740 return -1;
743 return index;
746 #endif /* ENABLE_SRP */