summaryrefslogtreecommitdiff
path: root/src/psk.c
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2005-11-07 22:24:48 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2005-11-07 22:24:48 +0000
commitad4ed44c65e753e6d3a00104c049dd81826ccbf3 (patch)
treec7511d77a37287b567c2f31f3e5dfa9af956d635 /src/psk.c
parent31168918162ee35315f025a9d8aeec67a81c7a7c (diff)
downloadgnutls-ad4ed44c65e753e6d3a00104c049dd81826ccbf3.tar.gz
This is the initial commit in the 1.3 branch. Ported from the PSK branch:
* PSK ciphersuites have been added. * The session resumption data are now system independent.
Diffstat (limited to 'src/psk.c')
-rw-r--r--src/psk.c260
1 files changed, 260 insertions, 0 deletions
diff --git a/src/psk.c b/src/psk.c
new file mode 100644
index 0000000000..f930b07c88
--- /dev/null
+++ b/src/psk.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2005 Free Software Foundation
+ *
+ * This file is part of GNUTLS.
+ *
+ * GNUTLS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GNUTLS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <config.h>
+
+#define _MAX(x,y) (x>y?x:y)
+
+#ifndef ENABLE_PSK
+
+#include <stdio.h>
+
+
+int main(int argc, char **argv)
+{
+ printf("\nPSK not supported. This program is a dummy.\n\n");
+ return 1;
+};
+
+void psktool_version(void)
+{
+ fprintf(stderr, "GNU TLS dummy psktool.\n");
+}
+
+#else
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/extra.h>
+#include <psk-gaa.h>
+
+#include <gc.h> /* for randomize */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifndef _WIN32
+# include <pwd.h>
+# include <unistd.h>
+#else
+# include <windows.h>
+#endif
+
+static int write_key(const char *username, const char *key, int key_size, char *passwd_file);
+
+void psktool_version(void)
+{
+ fprintf(stderr, "GNU TLS psktool, ");
+ fprintf(stderr, "version %s. Libgnutls %s.\n", LIBGNUTLS_VERSION,
+ gnutls_check_version(NULL));
+}
+
+
+#define KPASSWD "/etc/passwd.psk"
+#define MAX_KEY_SIZE 64
+int main(int argc, char **argv)
+{
+ gaainfo info;
+ int ret;
+ struct passwd *pwd;
+ unsigned char key[MAX_KEY_SIZE];
+ char hex_key[MAX_KEY_SIZE*2 +1];
+ gnutls_datum dkey;
+ size_t hex_key_size = sizeof( hex_key);
+
+ if ((ret = gnutls_global_init()) < 0) {
+ fprintf(stderr, "global_init: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+#ifdef HAVE_UMASK
+ umask(066);
+#endif
+
+ if (gaa(argc, argv, &info) != -1) {
+ fprintf(stderr, "Error in the arguments.\n");
+ return -1;
+ }
+
+ if (info.passwd == NULL)
+ info.passwd = KPASSWD;
+
+ if (info.username == NULL) {
+#ifndef _WIN32
+ pwd = getpwuid(getuid());
+
+ if (pwd == NULL) {
+ fprintf(stderr, "No such user\n");
+ return -1;
+ }
+
+ info.username = pwd->pw_name;
+#else
+ fprintf(stderr, "Please specify a user\n");
+ return -1;
+#endif
+ }
+
+ if ( info.key_size > MAX_KEY_SIZE) {
+ fprintf(stderr, "Key size is too long\n");
+ exit(1);
+ }
+
+ if (info.key_size < 1) info.key_size = 16;
+
+ ret = gc_pseudo_random( (char*)key, info.key_size);
+ if (ret != GC_OK) {
+ fprintf(stderr, "Not enough randomness\n");
+ exit(1);
+ }
+
+ printf("Generating a random key for user '%s'\n", info.username);
+
+ dkey.data = key;
+ dkey.size = info.key_size;
+ ret = gnutls_hex_encode( &dkey, hex_key, &hex_key_size);
+ if (ret < 0) {
+ fprintf(stderr, "HEX encoding error\n");
+ exit(1);
+ }
+
+ ret = write_key(info.username, hex_key, hex_key_size, info.passwd);
+ if (ret == 0)
+ printf("Key stored to %s\n", info.passwd);
+
+ return ret;
+}
+
+static int filecopy(char *src, char *dst)
+{
+ FILE *fd, *fd2;
+ char line[5 * 1024];
+ char *p;
+
+ fd = fopen(dst, "w");
+ if (fd == NULL) {
+ fprintf(stderr, "Cannot open '%s' for write\n", dst);
+ return -1;
+ }
+
+ fd2 = fopen(src, "r");
+ if (fd2 == NULL) {
+ /* empty file */
+ fclose(fd);
+ return 0;
+ }
+
+ line[sizeof(line) - 1] = 0;
+ do {
+ p = fgets(line, sizeof(line) - 1, fd2);
+ if (p == NULL)
+ break;
+
+ fputs(line, fd);
+ } while (1);
+
+ fclose(fd);
+ fclose(fd2);
+
+ return 0;
+}
+
+static int write_key(const char *username, const char *key, int key_size,
+ char *passwd_file)
+{
+ FILE *fd;
+ char line[5 * 1024];
+ char *p, *pp;
+ char tmpname[1024];
+
+
+ /* delete previous entry */
+ struct stat st;
+ FILE *fd2;
+ int put;
+
+ if (strlen(passwd_file) > sizeof(tmpname) + 5) {
+ fprintf(stderr, "file '%s' is tooooo long\n", passwd_file);
+ return -1;
+ }
+ strcpy(tmpname, passwd_file);
+ strcat(tmpname, ".tmp");
+
+ if (stat(tmpname, &st) != -1) {
+ fprintf(stderr, "file '%s' is locked\n", tmpname);
+ return -1;
+ }
+
+ if (filecopy(passwd_file, tmpname) != 0) {
+ fprintf(stderr, "Cannot copy '%s' to '%s'\n",
+ passwd_file, tmpname);
+ return -1;
+ }
+
+ fd = fopen(passwd_file, "w");
+ if (fd == NULL) {
+ fprintf(stderr, "Cannot open '%s' for write\n", passwd_file);
+ remove(tmpname);
+ return -1;
+ }
+
+ fd2 = fopen(tmpname, "r");
+ if (fd2 == NULL) {
+ fprintf(stderr, "Cannot open '%s' for read\n", tmpname);
+ remove(tmpname);
+ return -1;
+ }
+
+ put = 0;
+ do {
+ p = fgets(line, sizeof(line) - 1, fd2);
+ if (p == NULL)
+ break;
+
+ pp = strchr(line, ':');
+ if (pp == NULL)
+ continue;
+
+ if (strncmp
+ (p, username,
+ _MAX(strlen(username), (unsigned int) (pp - p))) == 0) {
+ put = 1;
+ fprintf(fd, "%s:%s\n", username, key);
+ } else {
+ fputs(line, fd);
+ }
+ } while (1);
+
+ if (put == 0) {
+ fprintf(fd, "%s:%s\n", username, key);
+ }
+
+ fclose(fd);
+ fclose(fd2);
+
+ remove(tmpname);
+
+
+ return 0;
+}
+
+#endif /* ENABLE_PSK */