GRUB-1.98 changes
[grub2/jjazz.git] / normal / auth.c
blob156b84c3744313d70cc8cc68ef675ff9d3f35c3b
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2009 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/auth.h>
20 #include <grub/list.h>
21 #include <grub/mm.h>
22 #include <grub/misc.h>
23 #include <grub/env.h>
24 #include <grub/normal.h>
25 #include <grub/time.h>
26 #include <grub/i18n.h>
28 struct grub_auth_user
30 struct grub_auth_user *next;
31 char *name;
32 grub_auth_callback_t callback;
33 void *arg;
34 int authenticated;
37 struct grub_auth_user *users = NULL;
39 grub_err_t
40 grub_auth_register_authentication (const char *user,
41 grub_auth_callback_t callback,
42 void *arg)
44 struct grub_auth_user *cur;
46 cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
47 if (!cur)
48 cur = grub_zalloc (sizeof (*cur));
49 if (!cur)
50 return grub_errno;
51 cur->callback = callback;
52 cur->arg = arg;
53 if (! cur->name)
55 cur->name = grub_strdup (user);
56 if (!cur->name)
58 grub_free (cur);
59 return grub_errno;
61 grub_list_push (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
63 return GRUB_ERR_NONE;
66 grub_err_t
67 grub_auth_unregister_authentication (const char *user)
69 struct grub_auth_user *cur;
70 cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
71 if (!cur)
72 return grub_error (GRUB_ERR_BAD_ARGUMENT, "user '%s' not found", user);
73 if (!cur->authenticated)
75 grub_free (cur->name);
76 grub_list_remove (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
77 grub_free (cur);
79 else
81 cur->callback = NULL;
82 cur->arg = NULL;
84 return GRUB_ERR_NONE;
87 grub_err_t
88 grub_auth_authenticate (const char *user)
90 struct grub_auth_user *cur;
92 cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
93 if (!cur)
94 cur = grub_zalloc (sizeof (*cur));
95 if (!cur)
96 return grub_errno;
98 cur->authenticated = 1;
100 if (! cur->name)
102 cur->name = grub_strdup (user);
103 if (!cur->name)
105 grub_free (cur);
106 return grub_errno;
108 grub_list_push (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
111 return GRUB_ERR_NONE;
114 grub_err_t
115 grub_auth_deauthenticate (const char *user)
117 struct grub_auth_user *cur;
118 cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
119 if (!cur)
120 return grub_error (GRUB_ERR_BAD_ARGUMENT, "user '%s' not found", user);
121 if (!cur->callback)
123 grub_free (cur->name);
124 grub_list_remove (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
125 grub_free (cur);
127 else
128 cur->authenticated = 0;
129 return GRUB_ERR_NONE;
132 static int
133 is_authenticated (const char *userlist)
135 const char *superusers;
137 auto int hook (grub_list_t item);
138 int hook (grub_list_t item)
140 const char *name;
141 if (!((struct grub_auth_user *) item)->authenticated)
142 return 0;
143 name = ((struct grub_auth_user *) item)->name;
145 return (userlist && grub_strword (userlist, name))
146 || grub_strword (superusers, name);
149 superusers = grub_env_get ("superusers");
151 if (!superusers)
152 return 1;
154 return grub_list_iterate (GRUB_AS_LIST (users), hook);
157 static int
158 grub_username_get (char buf[], unsigned buf_size)
160 unsigned cur_len = 0;
161 int key;
163 while (1)
165 key = GRUB_TERM_ASCII_CHAR (grub_getkey ());
166 if (key == '\n' || key == '\r')
167 break;
169 if (key == '\e')
171 cur_len = 0;
172 break;
175 if (key == '\b')
177 cur_len--;
178 grub_printf ("\b");
179 continue;
182 if (!grub_isprint (key))
183 continue;
185 if (cur_len + 2 < buf_size)
187 buf[cur_len++] = key;
188 grub_putchar (key);
192 grub_memset (buf + cur_len, 0, buf_size - cur_len);
194 grub_putchar ('\n');
195 grub_refresh ();
197 return (key != '\e');
200 grub_err_t
201 grub_auth_check_authentication (const char *userlist)
203 char login[1024];
204 struct grub_auth_user *cur = NULL;
205 grub_err_t err;
206 static unsigned long punishment_delay = 1;
207 char entered[GRUB_AUTH_MAX_PASSLEN];
209 auto int hook (grub_list_t item);
210 int hook (grub_list_t item)
212 if (grub_strcmp (login, ((struct grub_auth_user *) item)->name) == 0)
213 cur = (struct grub_auth_user *) item;
214 return 0;
217 auto int hook_any (grub_list_t item);
218 int hook_any (grub_list_t item)
220 if (((struct grub_auth_user *) item)->callback)
221 cur = (struct grub_auth_user *) item;
222 return 0;
225 grub_memset (login, 0, sizeof (login));
227 if (is_authenticated (userlist))
229 punishment_delay = 1;
230 return GRUB_ERR_NONE;
233 grub_puts_ (N_("Enter username: "));
235 if (!grub_username_get (login, sizeof (login) - 1))
236 goto access_denied;
238 grub_puts_ (N_("Enter password: "));
240 if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
241 goto access_denied;
243 grub_list_iterate (GRUB_AS_LIST (users), hook);
245 if (!cur || ! cur->callback)
246 goto access_denied;
248 err = cur->callback (login, entered, cur->arg);
249 if (is_authenticated (userlist))
251 punishment_delay = 1;
252 return GRUB_ERR_NONE;
255 access_denied:
256 grub_sleep (punishment_delay);
258 if (punishment_delay < GRUB_ULONG_MAX / 2)
259 punishment_delay *= 2;
261 return GRUB_ACCESS_DENIED;