The test now works.
[gnutls.git] / src / psk.c
blobbb3501f1d96280d7bf2602b435e0b06f422c1e39
1 /*
2 * Copyright (C) 2005, 2007, 2008 Free Software Foundation
4 * This file is part of GNUTLS.
6 * GNUTLS is free software: you can redistribute it and/or modify
7 * it 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,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU 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 <http://www.gnu.org/licenses/>.
20 #include <config.h>
22 #define _MAX(x,y) (x>y?x:y)
24 #ifndef ENABLE_PSK
26 #include <stdio.h>
29 int
30 main (int argc, char **argv)
32 printf ("\nPSK not supported. This program is a dummy.\n\n");
33 return 1;
36 void
37 psktool_version (void)
39 fprintf (stderr, "GNU TLS dummy psktool.\n");
42 #else
44 #include <stdio.h>
45 #include <string.h>
46 #include <stdlib.h>
47 #include <gnutls/gnutls.h>
48 #include <gnutls/extra.h>
49 #include <psk-gaa.h>
51 #include <gc.h> /* for randomize */
53 #include <sys/types.h>
54 #include <sys/stat.h>
56 #ifndef _WIN32
57 # include <pwd.h>
58 # include <unistd.h>
59 #else
60 # include <windows.h>
61 #endif
63 static int write_key (const char *username, const char *key, int key_size,
64 char *passwd_file);
66 void
67 psktool_version (void)
69 const char *v = gnutls_check_version (NULL);
71 printf ("psktool (GnuTLS) %s\n", LIBGNUTLS_VERSION);
72 if (strcmp (v, LIBGNUTLS_VERSION) != 0)
73 printf ("libgnutls %s\n", v);
77 #define KPASSWD "/etc/passwd.psk"
78 #define MAX_KEY_SIZE 64
79 int
80 main (int argc, char **argv)
82 gaainfo info;
83 int ret;
84 struct passwd *pwd;
85 unsigned char key[MAX_KEY_SIZE];
86 char hex_key[MAX_KEY_SIZE * 2 + 1];
87 gnutls_datum_t dkey;
88 size_t hex_key_size = sizeof (hex_key);
90 if ((ret = gnutls_global_init ()) < 0)
92 fprintf (stderr, "global_init: %s\n", gnutls_strerror (ret));
93 exit (1);
96 umask (066);
98 if (gaa (argc, argv, &info) != -1)
100 fprintf (stderr, "Error in the arguments.\n");
101 return -1;
104 if (info.passwd == NULL)
105 info.passwd = KPASSWD;
107 if (info.username == NULL)
109 #ifndef _WIN32
110 pwd = getpwuid (getuid ());
112 if (pwd == NULL)
114 fprintf (stderr, "No such user\n");
115 return -1;
118 info.username = pwd->pw_name;
119 #else
120 fprintf (stderr, "Please specify a user\n");
121 return -1;
122 #endif
125 if (info.key_size > MAX_KEY_SIZE)
127 fprintf (stderr, "Key size is too long\n");
128 exit (1);
131 if (info.netconf_hint)
133 char *passwd;
135 if (info.key_size != 0 && info.key_size != 20)
137 fprintf (stderr, "For netconf, key size must always be 20.\n");
138 exit (1);
141 passwd = getpass ("Enter password: ");
142 if (passwd == NULL)
144 fprintf (stderr, "Please specify a password\n");
145 exit (1);
148 ret = gnutls_psk_netconf_derive_key (passwd,
149 info.username,
150 info.netconf_hint,
151 &dkey);
153 else
155 if (info.key_size < 1)
156 info.key_size = 16;
158 printf ("Generating a random key for user '%s'\n", info.username);
160 ret = gc_pseudo_random ((char *) key, info.key_size);
161 if (ret != GC_OK)
163 fprintf (stderr, "Not enough randomness\n");
164 exit (1);
167 dkey.data = key;
168 dkey.size = info.key_size;
171 ret = gnutls_hex_encode (&dkey, hex_key, &hex_key_size);
172 if (info.netconf_hint)
173 gnutls_free (dkey.data);
174 if (ret < 0)
176 fprintf (stderr, "HEX encoding error\n");
177 exit (1);
180 ret = write_key (info.username, hex_key, hex_key_size, info.passwd);
181 if (ret == 0)
182 printf ("Key stored to %s\n", info.passwd);
184 return ret;
187 static int
188 filecopy (char *src, char *dst)
190 FILE *fd, *fd2;
191 char line[5 * 1024];
192 char *p;
194 fd = fopen (dst, "w");
195 if (fd == NULL)
197 fprintf (stderr, "Cannot open '%s' for write\n", dst);
198 return -1;
201 fd2 = fopen (src, "r");
202 if (fd2 == NULL)
204 /* empty file */
205 fclose (fd);
206 return 0;
209 line[sizeof (line) - 1] = 0;
212 p = fgets (line, sizeof (line) - 1, fd2);
213 if (p == NULL)
214 break;
216 fputs (line, fd);
218 while (1);
220 fclose (fd);
221 fclose (fd2);
223 return 0;
226 static int
227 write_key (const char *username, const char *key, int key_size,
228 char *passwd_file)
230 FILE *fd;
231 char line[5 * 1024];
232 char *p, *pp;
233 char tmpname[1024];
236 /* delete previous entry */
237 struct stat st;
238 FILE *fd2;
239 int put;
241 if (strlen (passwd_file) > sizeof (tmpname) + 5)
243 fprintf (stderr, "file '%s' is tooooo long\n", passwd_file);
244 return -1;
246 strcpy (tmpname, passwd_file);
247 strcat (tmpname, ".tmp");
249 if (stat (tmpname, &st) != -1)
251 fprintf (stderr, "file '%s' is locked\n", tmpname);
252 return -1;
255 if (filecopy (passwd_file, tmpname) != 0)
257 fprintf (stderr, "Cannot copy '%s' to '%s'\n", passwd_file, tmpname);
258 return -1;
261 fd = fopen (passwd_file, "w");
262 if (fd == NULL)
264 fprintf (stderr, "Cannot open '%s' for write\n", passwd_file);
265 remove (tmpname);
266 return -1;
269 fd2 = fopen (tmpname, "r");
270 if (fd2 == NULL)
272 fprintf (stderr, "Cannot open '%s' for read\n", tmpname);
273 remove (tmpname);
274 return -1;
277 put = 0;
280 p = fgets (line, sizeof (line) - 1, fd2);
281 if (p == NULL)
282 break;
284 pp = strchr (line, ':');
285 if (pp == NULL)
286 continue;
288 if (strncmp
289 (p, username,
290 _MAX (strlen (username), (unsigned int) (pp - p))) == 0)
292 put = 1;
293 fprintf (fd, "%s:%s\n", username, key);
295 else
297 fputs (line, fd);
300 while (1);
302 if (put == 0)
304 fprintf (fd, "%s:%s\n", username, key);
307 fclose (fd);
308 fclose (fd2);
310 remove (tmpname);
313 return 0;
316 #endif /* ENABLE_PSK */