cleaned up errno handling.
[gnutls.git] / lib / auth / psk_passwd.c
blob8e60bf2826e55bf284e08fbd899f740b05f97b7c
1 /*
2 * Copyright (C) 2005-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS 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 3 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 License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 /* Functions for operating in an PSK passwd file are included here */
25 #include <gnutls_int.h>
27 #ifdef ENABLE_PSK
29 #include "x509_b64.h"
30 #include "gnutls_errors.h"
31 #include <auth/psk_passwd.h>
32 #include <auth/psk.h>
33 #include "gnutls_auth.h"
34 #include "gnutls_dh.h"
35 #include "debug.h"
36 #include <gnutls_str.h>
37 #include <gnutls_datum.h>
38 #include <gnutls_num.h>
39 #include <random.h>
42 /* this function parses passwd.psk file. Format is:
43 * string(username):hex(passwd)
45 static int
46 pwd_put_values (gnutls_datum_t * psk, char *str)
48 char *p;
49 int len, ret;
50 size_t size;
52 p = strchr (str, ':');
53 if (p == NULL)
55 gnutls_assert ();
56 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
59 *p = '\0';
60 p++;
62 /* skip username
65 /* read the key
67 len = strlen (p);
68 if (p[len - 1] == '\n' || p[len - 1] == ' ')
69 len--;
71 size = psk->size = len / 2;
72 psk->data = gnutls_malloc (size);
73 if (psk->data == NULL)
75 gnutls_assert ();
76 return GNUTLS_E_MEMORY_ERROR;
79 ret = _gnutls_hex2bin (p, len, psk->data, &size);
80 psk->size = (unsigned int) size;
81 if (ret < 0)
83 gnutls_assert ();
84 return ret;
88 return 0;
93 /* Randomizes the given password entry. It actually sets a random password.
94 * Returns 0 on success.
96 static int
97 _randomize_psk (gnutls_datum_t * psk)
99 int ret;
101 psk->data = gnutls_malloc (16);
102 if (psk->data == NULL)
104 gnutls_assert ();
105 return GNUTLS_E_MEMORY_ERROR;
108 psk->size = 16;
110 ret = _gnutls_rnd (GNUTLS_RND_NONCE, (char *) psk->data, 16);
111 if (ret < 0)
113 gnutls_assert ();
114 return ret;
117 return 0;
120 /* Returns the PSK key of the given user.
121 * If the user doesn't exist a random password is returned instead.
124 _gnutls_psk_pwd_find_entry (gnutls_session_t session, char *username,
125 gnutls_datum_t * psk)
127 gnutls_psk_server_credentials_t cred;
128 FILE *fd;
129 char line[2 * 1024];
130 unsigned i, len;
131 int ret;
133 cred = (gnutls_psk_server_credentials_t)
134 _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);
135 if (cred == NULL)
137 gnutls_assert ();
138 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
141 /* if the callback which sends the parameters is
142 * set, use it.
144 if (cred->pwd_callback != NULL)
146 ret = cred->pwd_callback (session, username, psk);
148 if (ret == 1)
149 { /* the user does not exist */
150 ret = _randomize_psk (psk);
151 if (ret < 0)
153 gnutls_assert ();
154 return ret;
156 return 0;
159 if (ret < 0)
161 gnutls_assert ();
162 return GNUTLS_E_SRP_PWD_ERROR;
165 return 0;
168 /* The callback was not set. Proceed.
170 if (cred->password_file == NULL)
172 gnutls_assert ();
173 return GNUTLS_E_SRP_PWD_ERROR;
176 /* Open the selected password file.
178 fd = fopen (cred->password_file, "r");
179 if (fd == NULL)
181 gnutls_assert ();
182 return GNUTLS_E_SRP_PWD_ERROR;
185 len = strlen (username);
186 while (fgets (line, sizeof (line), fd) != NULL)
188 /* move to first ':' */
189 i = 0;
190 while ((line[i] != ':') && (line[i] != '\0') && (i < sizeof (line)))
192 i++;
195 if (strncmp (username, line, MAX (i, len)) == 0)
197 ret = pwd_put_values (psk, line);
198 fclose (fd);
199 if (ret < 0)
201 gnutls_assert ();
202 return GNUTLS_E_SRP_PWD_ERROR;
204 return 0;
207 fclose (fd);
209 /* user was not found. Fake him.
210 * the last index found and randomize the entry.
212 ret = _randomize_psk (psk);
213 if (ret < 0)
215 gnutls_assert ();
216 return ret;
219 return 0;
224 #endif /* ENABLE PSK */