_gnutls_strdatum_to_buf() will account for NULL input.
[gnutls.git] / src / psk.c
blob8c9e349cf84159827fb9f66e0ed6ca55a28068a2
1 /*
2 * Copyright (C) 2005-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/>.
21 #include <config.h>
23 /* Gnulib portability files. */
24 #include <version-etc.h>
25 #include <progname.h>
27 #ifndef ENABLE_PSK
29 #include <stdio.h>
31 int
32 main (int argc, char **argv)
34 printf ("\nPSK not supported. This program is a dummy.\n\n");
35 return 1;
38 #else
40 #include <stdio.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #include <gnutls/gnutls.h>
44 #include <psk-args.h>
46 #include <gnutls/crypto.h> /* for random */
48 #include <sys/types.h>
49 #include <sys/stat.h>
51 #ifndef _WIN32
52 #include <pwd.h>
53 #include <unistd.h>
54 #else
55 #include <windows.h>
56 #endif
58 /* Gnulib portability files. */
59 #include <minmax.h>
60 #include "getpass.h"
62 static int write_key (const char *username, const char *key, int key_size,
63 const char *passwd_file);
65 #define KPASSWD "/etc/passwd.psk"
66 #define MAX_KEY_SIZE 64
67 int
68 main (int argc, char **argv)
70 int ret;
71 #ifndef _WIN32
72 struct passwd *pwd;
73 #endif
74 unsigned char key[MAX_KEY_SIZE];
75 char hex_key[MAX_KEY_SIZE * 2 + 1];
76 int optct, key_size;
77 gnutls_datum_t dkey;
78 const char* passwd, *username;
79 size_t hex_key_size = sizeof (hex_key);
81 set_program_name (argv[0]);
83 if ((ret = gnutls_global_init ()) < 0)
85 fprintf (stderr, "global_init: %s\n", gnutls_strerror (ret));
86 exit (1);
89 umask (066);
91 optct = optionProcess( &psktoolOptions, argc, argv);
92 argc -= optct;
93 argv += optct;
95 if (!HAVE_OPT(PASSWD))
96 passwd = (char *) KPASSWD;
97 else
98 passwd = OPT_ARG(PASSWD);
100 if (!HAVE_OPT(USERNAME))
102 #ifndef _WIN32
103 pwd = getpwuid (getuid ());
105 if (pwd == NULL)
107 fprintf (stderr, "No such user\n");
108 return -1;
111 username = pwd->pw_name;
112 #else
113 fprintf (stderr, "Please specify a user\n");
114 return -1;
115 #endif
117 else
118 username = OPT_ARG(USERNAME);
120 if (HAVE_OPT(KEYSIZE) && OPT_VALUE_KEYSIZE > MAX_KEY_SIZE)
122 fprintf (stderr, "Key size is too long\n");
123 exit (1);
126 if (!HAVE_OPT(KEYSIZE) || OPT_VALUE_KEYSIZE < 1)
127 key_size = 16;
128 else
129 key_size = OPT_VALUE_KEYSIZE;
131 printf ("Generating a random key for user '%s'\n", username);
133 ret = gnutls_rnd (GNUTLS_RND_RANDOM, (char *) key, key_size);
134 if (ret < 0)
136 fprintf (stderr, "Not enough randomness\n");
137 exit (1);
140 dkey.data = key;
141 dkey.size = key_size;
143 ret = gnutls_hex_encode (&dkey, hex_key, &hex_key_size);
144 if (ret < 0)
146 fprintf (stderr, "HEX encoding error\n");
147 exit (1);
150 ret = write_key (username, hex_key, hex_key_size, passwd);
151 if (ret == 0)
152 printf ("Key stored to %s\n", passwd);
154 return ret;
157 static int
158 filecopy (const char *src, const char *dst)
160 FILE *fd, *fd2;
161 char line[5 * 1024];
162 char *p;
164 fd = fopen (dst, "w");
165 if (fd == NULL)
167 fprintf (stderr, "Cannot open '%s' for write\n", dst);
168 return -1;
171 fd2 = fopen (src, "r");
172 if (fd2 == NULL)
174 /* empty file */
175 fclose (fd);
176 return 0;
179 line[sizeof (line) - 1] = 0;
182 p = fgets (line, sizeof (line) - 1, fd2);
183 if (p == NULL)
184 break;
186 fputs (line, fd);
188 while (1);
190 fclose (fd);
191 fclose (fd2);
193 return 0;
196 static int
197 write_key (const char *username, const char *key, int key_size,
198 const char *passwd_file)
200 FILE *fd;
201 char line[5 * 1024];
202 char *p, *pp;
203 char tmpname[1024];
206 /* delete previous entry */
207 struct stat st;
208 FILE *fd2;
209 int put;
211 if (strlen (passwd_file) > sizeof (tmpname) + 5)
213 fprintf (stderr, "file '%s' is tooooo long\n", passwd_file);
214 return -1;
216 strcpy (tmpname, passwd_file);
217 strcat (tmpname, ".tmp");
219 if (stat (tmpname, &st) != -1)
221 fprintf (stderr, "file '%s' is locked\n", tmpname);
222 return -1;
225 if (filecopy (passwd_file, tmpname) != 0)
227 fprintf (stderr, "Cannot copy '%s' to '%s'\n", passwd_file, tmpname);
228 return -1;
231 fd = fopen (passwd_file, "w");
232 if (fd == NULL)
234 fprintf (stderr, "Cannot open '%s' for write\n", passwd_file);
235 remove (tmpname);
236 return -1;
239 fd2 = fopen (tmpname, "r");
240 if (fd2 == NULL)
242 fprintf (stderr, "Cannot open '%s' for read\n", tmpname);
243 remove (tmpname);
244 return -1;
247 put = 0;
250 p = fgets (line, sizeof (line) - 1, fd2);
251 if (p == NULL)
252 break;
254 pp = strchr (line, ':');
255 if (pp == NULL)
256 continue;
258 if (strncmp (p, username,
259 MAX (strlen (username), (unsigned int) (pp - p))) == 0)
261 put = 1;
262 fprintf (fd, "%s:%s\n", username, key);
264 else
266 fputs (line, fd);
269 while (1);
271 if (put == 0)
273 fprintf (fd, "%s:%s\n", username, key);
276 fclose (fd);
277 fclose (fd2);
279 remove (tmpname);
282 return 0;
285 #endif /* ENABLE_PSK */