Sync with TP.
[gnutls.git] / lib / auth_psk_passwd.c
blob98397a8c3cb7b154c4fee614301f5001fa72f3e5
1 /*
2 * Copyright (C) 2005, 2007, 2008, 2010 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * USA
25 /* Functions for operating in an PSK passwd file are included here */
27 #include <gnutls_int.h>
29 #ifdef ENABLE_PSK
31 #include "x509_b64.h"
32 #include "gnutls_errors.h"
33 #include <auth_psk_passwd.h>
34 #include "auth_psk.h"
35 #include "gnutls_auth.h"
36 #include "gnutls_dh.h"
37 #include "debug.h"
38 #include <gnutls_str.h>
39 #include <gnutls_datum.h>
40 #include <gnutls_num.h>
41 #include <random.h>
44 /* this function parses passwd.psk file. Format is:
45 * string(username):hex(passwd)
47 static int
48 pwd_put_values (gnutls_datum_t * psk, char *str)
50 char *p;
51 int len, ret;
52 size_t size;
54 p = strchr (str, ':');
55 if (p == NULL)
57 gnutls_assert ();
58 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
61 *p = '\0';
62 p++;
64 /* skip username
67 /* read the key
69 len = strlen (p);
70 if (p[len - 1] == '\n' || p[len - 1] == ' ')
71 len--;
73 size = psk->size = len / 2;
74 psk->data = gnutls_malloc (size);
75 if (psk->data == NULL)
77 gnutls_assert ();
78 return GNUTLS_E_MEMORY_ERROR;
81 ret = _gnutls_hex2bin ((opaque *) p, len, psk->data, &size);
82 psk->size = (unsigned int) size;
83 if (ret < 0)
85 gnutls_assert ();
86 return ret;
90 return 0;
95 /* Randomizes the given password entry. It actually sets a random password.
96 * Returns 0 on success.
98 static int
99 _randomize_psk (gnutls_datum_t * psk)
101 int ret;
103 psk->data = gnutls_malloc (16);
104 if (psk->data == NULL)
106 gnutls_assert ();
107 return GNUTLS_E_MEMORY_ERROR;
110 psk->size = 16;
112 ret = _gnutls_rnd (GNUTLS_RND_NONCE, (char *) psk->data, 16);
113 if (ret < 0)
115 gnutls_assert ();
116 return ret;
119 return 0;
122 /* Returns the PSK key of the given user.
123 * If the user doesn't exist a random password is returned instead.
126 _gnutls_psk_pwd_find_entry (gnutls_session_t session, char *username,
127 gnutls_datum_t * psk)
129 gnutls_psk_server_credentials_t cred;
130 FILE *fd;
131 char line[2 * 1024];
132 unsigned i, len;
133 int ret;
135 cred = (gnutls_psk_server_credentials_t)
136 _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);
137 if (cred == NULL)
139 gnutls_assert ();
140 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
143 /* if the callback which sends the parameters is
144 * set, use it.
146 if (cred->pwd_callback != NULL)
148 ret = cred->pwd_callback (session, username, psk);
150 if (ret == 1)
151 { /* the user does not exist */
152 ret = _randomize_psk (psk);
153 if (ret < 0)
155 gnutls_assert ();
156 return ret;
158 return 0;
161 if (ret < 0)
163 gnutls_assert ();
164 return GNUTLS_E_SRP_PWD_ERROR;
167 return 0;
170 /* The callback was not set. Proceed.
172 if (cred->password_file == NULL)
174 gnutls_assert ();
175 return GNUTLS_E_SRP_PWD_ERROR;
178 /* Open the selected password file.
180 fd = fopen (cred->password_file, "r");
181 if (fd == NULL)
183 gnutls_assert ();
184 return GNUTLS_E_SRP_PWD_ERROR;
187 len = strlen (username);
188 while (fgets (line, sizeof (line), fd) != NULL)
190 /* move to first ':' */
191 i = 0;
192 while ((line[i] != ':') && (line[i] != '\0') && (i < sizeof (line)))
194 i++;
197 if (strncmp (username, line, MAX (i, len)) == 0)
199 ret = pwd_put_values (psk, line);
200 fclose (fd);
201 if (ret < 0)
203 gnutls_assert ();
204 return GNUTLS_E_SRP_PWD_ERROR;
206 return 0;
209 fclose (fd);
211 /* user was not found. Fake him.
212 * the last index found and randomize the entry.
214 ret = _randomize_psk (psk);
215 if (ret < 0)
217 gnutls_assert ();
218 return ret;
221 return 0;
226 #endif /* ENABLE PSK */