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>
22 #include <grub/misc.h>
24 #include <grub/normal.h>
25 #include <grub/time.h>
26 #include <grub/i18n.h>
30 struct grub_auth_user
*next
;
32 grub_auth_callback_t callback
;
37 struct grub_auth_user
*users
= NULL
;
40 grub_auth_register_authentication (const char *user
,
41 grub_auth_callback_t callback
,
44 struct grub_auth_user
*cur
;
46 cur
= grub_named_list_find (GRUB_AS_NAMED_LIST (users
), user
);
48 cur
= grub_zalloc (sizeof (*cur
));
51 cur
->callback
= callback
;
55 cur
->name
= grub_strdup (user
);
61 grub_list_push (GRUB_AS_LIST_P (&users
), GRUB_AS_LIST (cur
));
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
);
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
));
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
);
94 cur
= grub_zalloc (sizeof (*cur
));
98 cur
->authenticated
= 1;
102 cur
->name
= grub_strdup (user
);
108 grub_list_push (GRUB_AS_LIST_P (&users
), GRUB_AS_LIST (cur
));
111 return GRUB_ERR_NONE
;
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
);
120 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "user '%s' not found", user
);
123 grub_free (cur
->name
);
124 grub_list_remove (GRUB_AS_LIST_P (&users
), GRUB_AS_LIST (cur
));
128 cur
->authenticated
= 0;
129 return GRUB_ERR_NONE
;
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
)
141 if (!((struct grub_auth_user
*) item
)->authenticated
)
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");
154 return grub_list_iterate (GRUB_AS_LIST (users
), hook
);
158 grub_username_get (char buf
[], unsigned buf_size
)
160 unsigned cur_len
= 0;
165 key
= GRUB_TERM_ASCII_CHAR (grub_getkey ());
166 if (key
== '\n' || key
== '\r')
182 if (!grub_isprint (key
))
185 if (cur_len
+ 2 < buf_size
)
187 buf
[cur_len
++] = key
;
192 grub_memset (buf
+ cur_len
, 0, buf_size
- cur_len
);
197 return (key
!= '\e');
201 grub_auth_check_authentication (const char *userlist
)
204 struct grub_auth_user
*cur
= NULL
;
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
;
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
;
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))
238 grub_puts_ (N_("Enter password: "));
240 if (!grub_password_get (entered
, GRUB_AUTH_MAX_PASSLEN
))
243 grub_list_iterate (GRUB_AS_LIST (users
), hook
);
245 if (!cur
|| ! cur
->callback
)
248 err
= cur
->callback (login
, entered
, cur
->arg
);
249 if (is_authenticated (userlist
))
251 punishment_delay
= 1;
252 return GRUB_ERR_NONE
;
256 grub_sleep (punishment_delay
);
258 if (punishment_delay
< GRUB_ULONG_MAX
/ 2)
259 punishment_delay
*= 2;
261 return GRUB_ACCESS_DENIED
;