]>
Commit | Line | Data |
---|---|---|
092fd48a VS |
1 | /* |
2 | * GRUB -- GRand Unified Bootloader | |
a37376e7 | 3 | * Copyright (C) 2000, 2001, 2010 Free Software Foundation, Inc. |
092fd48a VS |
4 | * |
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. | |
9 | * | |
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. | |
14 | * | |
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/>. | |
17 | */ | |
18 | ||
19 | #include <grub/types.h> | |
20 | #include <grub/misc.h> | |
21 | #include <grub/command.h> | |
22 | #include <grub/mm.h> | |
23 | #include <grub/err.h> | |
24 | #include <grub/dl.h> | |
25 | #include <grub/file.h> | |
092fd48a VS |
26 | #include <grub/normal.h> |
27 | #include <grub/script_sh.h> | |
28 | #include <grub/i18n.h> | |
68cc4355 | 29 | #include <grub/term.h> |
fff175c7 | 30 | #include <grub/legacy_parse.h> |
a37376e7 VS |
31 | #include <grub/crypto.h> |
32 | #include <grub/auth.h> | |
64ad6157 VS |
33 | #include <grub/disk.h> |
34 | #include <grub/partition.h> | |
092fd48a | 35 | |
e745cf0c VS |
36 | GRUB_MOD_LICENSE ("GPLv3+"); |
37 | ||
092fd48a VS |
38 | static grub_err_t |
39 | legacy_file (const char *filename) | |
40 | { | |
41 | grub_file_t file; | |
42 | char *entryname = NULL, *entrysrc = NULL; | |
43 | grub_menu_t menu; | |
6c6850ae VS |
44 | char *suffix = grub_strdup (""); |
45 | ||
46 | auto grub_err_t getline (char **line, int cont); | |
47 | grub_err_t getline (char **line, | |
48 | int cont __attribute__ ((unused))) | |
49 | { | |
50 | *line = 0; | |
51 | return GRUB_ERR_NONE; | |
52 | } | |
53 | ||
54 | if (!suffix) | |
55 | return grub_errno; | |
092fd48a | 56 | |
bd960307 | 57 | file = grub_file_open (filename); |
092fd48a VS |
58 | if (! file) |
59 | return grub_errno; | |
60 | ||
61 | menu = grub_env_get_menu (); | |
62 | if (! menu) | |
63 | { | |
64 | menu = grub_zalloc (sizeof (*menu)); | |
65 | if (! menu) | |
66 | return grub_errno; | |
67 | ||
68 | grub_env_set_menu (menu); | |
69 | } | |
70 | ||
71 | while (1) | |
72 | { | |
73 | char *buf = grub_file_getline (file); | |
64ad6157 | 74 | char *parsed = NULL; |
092fd48a VS |
75 | |
76 | if (!buf && grub_errno) | |
77 | { | |
78 | grub_file_close (file); | |
79 | return grub_errno; | |
80 | } | |
81 | ||
82 | if (!buf) | |
83 | break; | |
84 | ||
85 | { | |
86 | char *oldname = NULL; | |
e64334df | 87 | char *newsuffix; |
47a77af5 VS |
88 | char *ptr; |
89 | ||
90 | for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); | |
092fd48a VS |
91 | |
92 | oldname = entryname; | |
47a77af5 VS |
93 | parsed = grub_legacy_parse (ptr, &entryname, &newsuffix); |
94 | grub_free (buf); | |
64ad6157 | 95 | buf = NULL; |
e64334df | 96 | if (newsuffix) |
6c6850ae VS |
97 | { |
98 | char *t; | |
99 | ||
100 | t = suffix; | |
101 | suffix = grub_realloc (suffix, grub_strlen (suffix) | |
e64334df | 102 | + grub_strlen (newsuffix) + 1); |
6c6850ae VS |
103 | if (!suffix) |
104 | { | |
105 | grub_free (t); | |
106 | grub_free (entrysrc); | |
107 | grub_free (parsed); | |
e64334df | 108 | grub_free (newsuffix); |
6c6850ae VS |
109 | grub_free (suffix); |
110 | return grub_errno; | |
111 | } | |
e64334df VS |
112 | grub_memcpy (suffix + grub_strlen (suffix), newsuffix, |
113 | grub_strlen (newsuffix) + 1); | |
114 | grub_free (newsuffix); | |
115 | newsuffix = NULL; | |
6c6850ae | 116 | } |
092fd48a VS |
117 | if (oldname != entryname && oldname) |
118 | { | |
119 | const char **args = grub_malloc (sizeof (args[0])); | |
120 | if (!args) | |
121 | { | |
122 | grub_file_close (file); | |
123 | return grub_errno; | |
124 | } | |
125 | args[0] = oldname; | |
bd960307 | 126 | grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, |
fc55cc4c | 127 | entrysrc, 0); |
64ad6157 VS |
128 | grub_free (args); |
129 | entrysrc[0] = 0; | |
130 | grub_free (oldname); | |
092fd48a VS |
131 | } |
132 | } | |
133 | ||
134 | if (parsed && !entryname) | |
135 | { | |
092fd48a | 136 | grub_normal_parse_line (parsed, getline); |
67cb07a3 | 137 | grub_print_error (); |
092fd48a | 138 | grub_free (parsed); |
64ad6157 | 139 | parsed = NULL; |
092fd48a VS |
140 | } |
141 | else if (parsed) | |
142 | { | |
143 | if (!entrysrc) | |
144 | entrysrc = parsed; | |
145 | else | |
146 | { | |
147 | char *t; | |
148 | ||
149 | t = entrysrc; | |
150 | entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc) | |
151 | + grub_strlen (parsed) + 1); | |
152 | if (!entrysrc) | |
153 | { | |
154 | grub_free (t); | |
155 | grub_free (parsed); | |
6c6850ae | 156 | grub_free (suffix); |
092fd48a VS |
157 | return grub_errno; |
158 | } | |
68cc4355 | 159 | grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed, |
092fd48a VS |
160 | grub_strlen (parsed) + 1); |
161 | grub_free (parsed); | |
162 | parsed = NULL; | |
163 | } | |
164 | } | |
165 | } | |
166 | grub_file_close (file); | |
167 | ||
168 | if (entryname) | |
169 | { | |
170 | const char **args = grub_malloc (sizeof (args[0])); | |
171 | if (!args) | |
172 | { | |
173 | grub_file_close (file); | |
174 | return grub_errno; | |
175 | } | |
176 | args[0] = entryname; | |
fc55cc4c | 177 | grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, entrysrc, 0); |
64ad6157 | 178 | grub_free (args); |
092fd48a VS |
179 | } |
180 | ||
6c6850ae VS |
181 | grub_normal_parse_line (suffix, getline); |
182 | grub_print_error (); | |
183 | grub_free (suffix); | |
64ad6157 | 184 | grub_free (entrysrc); |
6c6850ae | 185 | |
092fd48a VS |
186 | return GRUB_ERR_NONE; |
187 | } | |
188 | ||
189 | static grub_err_t | |
57f20e67 | 190 | grub_cmd_legacy_source (struct grub_command *cmd, |
092fd48a VS |
191 | int argc, char **args) |
192 | { | |
57f20e67 | 193 | int new_env, extractor; |
092fd48a | 194 | grub_err_t ret; |
57f20e67 | 195 | |
092fd48a VS |
196 | if (argc != 1) |
197 | return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); | |
198 | ||
57f20e67 | 199 | extractor = (cmd->name[0] == 'e'); |
f1808884 VS |
200 | new_env = (cmd->name[extractor ? (sizeof ("extract_legacy_entries_") - 1) |
201 | : (sizeof ("legacy_") - 1)] == 'c'); | |
57f20e67 VS |
202 | |
203 | if (new_env) | |
204 | grub_cls (); | |
205 | ||
206 | if (new_env && !extractor) | |
207 | grub_env_context_open (); | |
208 | if (extractor) | |
209 | grub_env_extractor_open (!new_env); | |
092fd48a VS |
210 | |
211 | ret = legacy_file (args[0]); | |
57f20e67 | 212 | |
f1808884 VS |
213 | if (new_env) |
214 | { | |
215 | grub_menu_t menu; | |
216 | menu = grub_env_get_menu (); | |
217 | if (menu && menu->size) | |
dcb883b1 | 218 | grub_show_menu (menu, 1, 0); |
f1808884 VS |
219 | if (!extractor) |
220 | grub_env_context_close (); | |
221 | } | |
57f20e67 VS |
222 | if (extractor) |
223 | grub_env_extractor_close (!new_env); | |
092fd48a VS |
224 | |
225 | return ret; | |
226 | } | |
227 | ||
8fc6a271 VS |
228 | static enum |
229 | { | |
230 | GUESS_IT, LINUX, MULTIBOOT, KFREEBSD, KNETBSD, KOPENBSD | |
231 | } kernel_type; | |
232 | ||
233 | static grub_err_t | |
234 | grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), | |
235 | int argc, char **args) | |
236 | { | |
237 | int i; | |
6bdda8f8 | 238 | #ifdef TODO |
8fc6a271 | 239 | int no_mem_option = 0; |
6bdda8f8 | 240 | #endif |
8fc6a271 | 241 | struct grub_command *cmd; |
9fb175ed VS |
242 | char **cutargs; |
243 | int cutargc; | |
64ad6157 | 244 | |
8fc6a271 VS |
245 | for (i = 0; i < 2; i++) |
246 | { | |
247 | /* FIXME: really support this. */ | |
248 | if (argc >= 1 && grub_strcmp (args[0], "--no-mem-option") == 0) | |
249 | { | |
6bdda8f8 | 250 | #ifdef TODO |
8fc6a271 | 251 | no_mem_option = 1; |
6bdda8f8 | 252 | #endif |
8fc6a271 VS |
253 | argc--; |
254 | args++; | |
255 | continue; | |
256 | } | |
257 | ||
2a87d7d1 | 258 | /* linux16 handles both zImages and bzImages. */ |
8fc6a271 VS |
259 | if (argc >= 1 && (grub_strcmp (args[0], "--type=linux") == 0 |
260 | || grub_strcmp (args[0], "--type=biglinux") == 0)) | |
261 | { | |
262 | kernel_type = LINUX; | |
263 | argc--; | |
264 | args++; | |
265 | continue; | |
266 | } | |
267 | ||
268 | if (argc >= 1 && grub_strcmp (args[0], "--type=multiboot") == 0) | |
269 | { | |
270 | kernel_type = MULTIBOOT; | |
271 | argc--; | |
272 | args++; | |
273 | continue; | |
274 | } | |
275 | ||
276 | if (argc >= 1 && grub_strcmp (args[0], "--type=freebsd") == 0) | |
277 | { | |
278 | kernel_type = KFREEBSD; | |
279 | argc--; | |
280 | args++; | |
281 | continue; | |
282 | } | |
283 | ||
284 | if (argc >= 1 && grub_strcmp (args[0], "--type=openbsd") == 0) | |
285 | { | |
286 | kernel_type = KOPENBSD; | |
287 | argc--; | |
288 | args++; | |
289 | continue; | |
290 | } | |
291 | ||
292 | if (argc >= 1 && grub_strcmp (args[0], "--type=netbsd") == 0) | |
293 | { | |
294 | kernel_type = KNETBSD; | |
295 | argc--; | |
296 | args++; | |
297 | continue; | |
298 | } | |
299 | } | |
300 | ||
9fb175ed | 301 | if (argc < 2) |
8fc6a271 VS |
302 | return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename required"); |
303 | ||
bd960307 | 304 | cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1)); |
9fb175ed | 305 | cutargc = argc - 1; |
bd960307 | 306 | grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2)); |
9fb175ed VS |
307 | cutargs[0] = args[0]; |
308 | ||
8fc6a271 VS |
309 | do |
310 | { | |
311 | /* First try Linux. */ | |
312 | if (kernel_type == GUESS_IT || kernel_type == LINUX) | |
313 | { | |
314 | cmd = grub_command_find ("linux16"); | |
315 | if (cmd) | |
316 | { | |
9fb175ed | 317 | if (!(cmd->func) (cmd, cutargc, cutargs)) |
8fc6a271 VS |
318 | { |
319 | kernel_type = LINUX; | |
320 | return GRUB_ERR_NONE; | |
321 | } | |
322 | } | |
323 | grub_errno = GRUB_ERR_NONE; | |
324 | } | |
325 | ||
326 | /* Then multiboot. */ | |
8fc6a271 VS |
327 | if (kernel_type == GUESS_IT || kernel_type == MULTIBOOT) |
328 | { | |
329 | cmd = grub_command_find ("multiboot"); | |
330 | if (cmd) | |
331 | { | |
332 | if (!(cmd->func) (cmd, argc, args)) | |
333 | { | |
334 | kernel_type = MULTIBOOT; | |
335 | return GRUB_ERR_NONE; | |
336 | } | |
337 | } | |
338 | grub_errno = GRUB_ERR_NONE; | |
339 | } | |
340 | ||
64ad6157 VS |
341 | { |
342 | int bsd_device = -1; | |
343 | int bsd_slice = -1; | |
344 | int bsd_part = -1; | |
8fc6a271 | 345 | { |
64ad6157 | 346 | grub_device_t dev; |
d35d0d37 | 347 | const char *hdbiasstr; |
64ad6157 VS |
348 | int hdbias = 0; |
349 | hdbiasstr = grub_env_get ("legacy_hdbias"); | |
350 | if (hdbiasstr) | |
8fc6a271 | 351 | { |
64ad6157 VS |
352 | hdbias = grub_strtoul (hdbiasstr, 0, 0); |
353 | grub_errno = GRUB_ERR_NONE; | |
354 | } | |
355 | dev = grub_device_open (0); | |
356 | if (dev && dev->disk | |
357 | && dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID | |
358 | && dev->disk->dev->id >= 0x80 && dev->disk->dev->id <= 0x90) | |
359 | { | |
360 | struct grub_partition *part = dev->disk->partition; | |
361 | bsd_device = dev->disk->id - 0x80 - hdbias; | |
362 | if (part && (grub_strcmp (part->partmap->name, "netbsd") == 0 | |
363 | || grub_strcmp (part->partmap->name, "openbsd") == 0 | |
364 | || grub_strcmp (part->partmap->name, "bsd") == 0)) | |
8fc6a271 | 365 | { |
64ad6157 VS |
366 | bsd_part = part->number; |
367 | part = part->parent; | |
8fc6a271 | 368 | } |
64ad6157 VS |
369 | if (part && grub_strcmp (part->partmap->name, "msdos") == 0) |
370 | bsd_slice = part->number; | |
8fc6a271 | 371 | } |
8fc6a271 | 372 | } |
64ad6157 VS |
373 | |
374 | /* k*BSD didn't really work well with grub-legacy. */ | |
375 | if (kernel_type == GUESS_IT || kernel_type == KFREEBSD) | |
376 | { | |
377 | char buf[sizeof("adXXXXXXXXXXXXsXXXXXXXXXXXXYYY")]; | |
378 | if (bsd_device != -1) | |
379 | { | |
380 | if (bsd_slice != -1 && bsd_part != -1) | |
381 | grub_snprintf(buf, sizeof(buf), "ad%ds%d%c", bsd_device, | |
382 | bsd_slice, 'a' + bsd_part); | |
383 | else if (bsd_slice != -1) | |
384 | grub_snprintf(buf, sizeof(buf), "ad%ds%d", bsd_device, | |
385 | bsd_slice); | |
386 | else | |
387 | grub_snprintf(buf, sizeof(buf), "ad%d", bsd_device); | |
388 | grub_env_set ("kFreeBSD.vfs.root.mountfrom", buf); | |
389 | } | |
390 | else | |
391 | grub_env_unset ("kFreeBSD.vfs.root.mountfrom"); | |
392 | cmd = grub_command_find ("kfreebsd"); | |
393 | if (cmd) | |
394 | { | |
395 | if (!(cmd->func) (cmd, cutargc, cutargs)) | |
396 | { | |
397 | kernel_type = KFREEBSD; | |
398 | return GRUB_ERR_NONE; | |
399 | } | |
400 | } | |
401 | grub_errno = GRUB_ERR_NONE; | |
402 | } | |
8fc6a271 | 403 | { |
64ad6157 VS |
404 | char **bsdargs; |
405 | int bsdargc; | |
406 | char bsddevname[sizeof ("wdXXXXXXXXXXXXY")]; | |
407 | if (bsd_device == -1) | |
8fc6a271 | 408 | { |
64ad6157 VS |
409 | bsdargs = cutargs; |
410 | bsdargc = cutargc; | |
411 | } | |
412 | else | |
413 | { | |
414 | bsdargc = cutargc + 2; | |
415 | bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc); | |
416 | grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0])); | |
417 | bsdargs[argc] = "-r"; | |
418 | bsdargs[argc + 1] = bsddevname; | |
419 | grub_snprintf (bsddevname, sizeof (bsddevname), | |
420 | "wd%d%c", bsd_device, | |
421 | bsd_part != -1 ? bsd_part + 'a' : 'c'); | |
422 | } | |
423 | if (kernel_type == GUESS_IT || kernel_type == KNETBSD) | |
424 | { | |
425 | cmd = grub_command_find ("knetbsd"); | |
426 | if (cmd) | |
8fc6a271 | 427 | { |
64ad6157 VS |
428 | if (!(cmd->func) (cmd, bsdargc, bsdargs)) |
429 | { | |
430 | kernel_type = KNETBSD; | |
431 | return GRUB_ERR_NONE; | |
432 | } | |
8fc6a271 | 433 | } |
64ad6157 | 434 | grub_errno = GRUB_ERR_NONE; |
8fc6a271 | 435 | } |
64ad6157 | 436 | if (kernel_type == GUESS_IT || kernel_type == KOPENBSD) |
8fc6a271 | 437 | { |
64ad6157 VS |
438 | cmd = grub_command_find ("kopenbsd"); |
439 | if (cmd) | |
8fc6a271 | 440 | { |
64ad6157 VS |
441 | if (!(cmd->func) (cmd, bsdargc, bsdargs)) |
442 | { | |
443 | kernel_type = KOPENBSD; | |
444 | return GRUB_ERR_NONE; | |
445 | } | |
8fc6a271 | 446 | } |
64ad6157 | 447 | grub_errno = GRUB_ERR_NONE; |
8fc6a271 | 448 | } |
64ad6157 VS |
449 | if (bsdargs != cutargs) |
450 | grub_free (bsdargs); | |
8fc6a271 | 451 | } |
64ad6157 | 452 | } |
8fc6a271 VS |
453 | } |
454 | while (0); | |
455 | ||
456 | return grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s\n", | |
457 | args[0]); | |
458 | } | |
459 | ||
460 | static grub_err_t | |
461 | grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)), | |
462 | int argc, char **args) | |
463 | { | |
464 | struct grub_command *cmd; | |
465 | ||
466 | if (kernel_type == LINUX) | |
467 | { | |
468 | cmd = grub_command_find ("initrd16"); | |
469 | if (!cmd) | |
470 | return grub_error (GRUB_ERR_BAD_ARGUMENT, "command initrd16 not found"); | |
471 | ||
472 | return cmd->func (cmd, argc, args); | |
473 | } | |
474 | if (kernel_type == MULTIBOOT) | |
475 | { | |
8fc6a271 VS |
476 | cmd = grub_command_find ("module"); |
477 | if (!cmd) | |
478 | return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found"); | |
479 | ||
480 | return cmd->func (cmd, argc, args); | |
481 | } | |
482 | ||
483 | return grub_error (GRUB_ERR_BAD_ARGUMENT, | |
484 | "no kernel with module support is loaded in legacy way"); | |
485 | } | |
486 | ||
237a43b1 VS |
487 | static grub_err_t |
488 | grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused)), | |
489 | int argc, char **args) | |
490 | { | |
491 | struct grub_command *cmd; | |
492 | ||
493 | if (kernel_type == LINUX) | |
494 | { | |
495 | cmd = grub_command_find ("initrd16"); | |
496 | if (!cmd) | |
497 | return grub_error (GRUB_ERR_BAD_ARGUMENT, "command initrd16 not found"); | |
498 | ||
499 | return cmd->func (cmd, argc, args); | |
500 | } | |
501 | if (kernel_type == MULTIBOOT) | |
502 | { | |
503 | char **newargs; | |
504 | grub_err_t err; | |
505 | newargs = grub_malloc ((argc + 1) * sizeof (newargs[0])); | |
506 | if (!newargs) | |
507 | return grub_errno; | |
508 | grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0])); | |
509 | newargs[0] = "--nounzip"; | |
510 | cmd = grub_command_find ("module"); | |
511 | if (!cmd) | |
512 | return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found"); | |
513 | ||
514 | err = cmd->func (cmd, argc + 1, newargs); | |
515 | grub_free (newargs); | |
516 | return err; | |
517 | } | |
518 | ||
519 | return grub_error (GRUB_ERR_BAD_ARGUMENT, | |
520 | "no kernel with module support is loaded in legacy way"); | |
521 | } | |
522 | ||
a37376e7 VS |
523 | static grub_err_t |
524 | check_password_deny (const char *user __attribute__ ((unused)), | |
525 | const char *entered __attribute__ ((unused)), | |
526 | void *password __attribute__ ((unused))) | |
527 | { | |
528 | return GRUB_ACCESS_DENIED; | |
529 | } | |
530 | ||
531 | #define MD5_HASHLEN 16 | |
532 | ||
533 | struct legacy_md5_password | |
534 | { | |
535 | grub_uint8_t *salt; | |
536 | int saltlen; | |
537 | grub_uint8_t hash[MD5_HASHLEN]; | |
538 | }; | |
539 | ||
540 | static int | |
541 | check_password_md5_real (const char *entered, | |
542 | struct legacy_md5_password *pw) | |
543 | { | |
544 | int enteredlen = grub_strlen (entered); | |
545 | unsigned char alt_result[MD5_HASHLEN]; | |
546 | unsigned char *digest; | |
547 | grub_uint8_t ctx[GRUB_MD_MD5->contextsize]; | |
548 | int i; | |
549 | ||
550 | GRUB_MD_MD5->init (ctx); | |
551 | GRUB_MD_MD5->write (ctx, entered, enteredlen); | |
552 | GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3); | |
553 | GRUB_MD_MD5->write (ctx, entered, enteredlen); | |
554 | digest = GRUB_MD_MD5->read (ctx); | |
555 | GRUB_MD_MD5->final (ctx); | |
556 | memcpy (alt_result, digest, MD5_HASHLEN); | |
557 | ||
558 | GRUB_MD_MD5->init (ctx); | |
559 | GRUB_MD_MD5->write (ctx, entered, enteredlen); | |
560 | GRUB_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */ | |
561 | for (i = enteredlen; i > 16; i -= 16) | |
562 | GRUB_MD_MD5->write (ctx, alt_result, 16); | |
563 | GRUB_MD_MD5->write (ctx, alt_result, i); | |
564 | ||
565 | for (i = enteredlen; i > 0; i >>= 1) | |
566 | GRUB_MD_MD5->write (ctx, entered + ((i & 1) ? enteredlen : 0), 1); | |
567 | digest = GRUB_MD_MD5->read (ctx); | |
568 | GRUB_MD_MD5->final (ctx); | |
569 | ||
570 | for (i = 0; i < 1000; i++) | |
571 | { | |
572 | memcpy (alt_result, digest, 16); | |
573 | ||
574 | GRUB_MD_MD5->init (ctx); | |
575 | if ((i & 1) != 0) | |
576 | GRUB_MD_MD5->write (ctx, entered, enteredlen); | |
577 | else | |
578 | GRUB_MD_MD5->write (ctx, alt_result, 16); | |
579 | ||
580 | if (i % 3 != 0) | |
581 | GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3); | |
582 | ||
583 | if (i % 7 != 0) | |
584 | GRUB_MD_MD5->write (ctx, entered, enteredlen); | |
585 | ||
586 | if ((i & 1) != 0) | |
587 | GRUB_MD_MD5->write (ctx, alt_result, 16); | |
588 | else | |
589 | GRUB_MD_MD5->write (ctx, entered, enteredlen); | |
590 | digest = GRUB_MD_MD5->read (ctx); | |
591 | GRUB_MD_MD5->final (ctx); | |
592 | } | |
593 | ||
594 | return (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0); | |
595 | } | |
596 | ||
597 | static grub_err_t | |
598 | check_password_md5 (const char *user, | |
599 | const char *entered, | |
600 | void *password) | |
601 | { | |
602 | if (!check_password_md5_real (entered, password)) | |
603 | return GRUB_ACCESS_DENIED; | |
604 | ||
605 | grub_auth_authenticate (user); | |
606 | ||
607 | return GRUB_ERR_NONE; | |
608 | } | |
609 | ||
610 | static inline int | |
611 | ib64t (char c) | |
612 | { | |
613 | if (c == '.') | |
614 | return 0; | |
615 | if (c == '/') | |
616 | return 1; | |
617 | if (c >= '0' && c <= '9') | |
618 | return c - '0' + 2; | |
619 | if (c >= 'A' && c <= 'Z') | |
620 | return c - 'A' + 12; | |
621 | if (c >= 'a' && c <= 'z') | |
622 | return c - 'a' + 38; | |
623 | return -1; | |
624 | } | |
625 | ||
e2830452 VS |
626 | static struct legacy_md5_password * |
627 | parse_legacy_md5 (int argc, char **args) | |
a37376e7 VS |
628 | { |
629 | const char *salt, *saltend; | |
a37376e7 VS |
630 | struct legacy_md5_password *pw = NULL; |
631 | int i; | |
e2830452 | 632 | const char *p; |
a37376e7 | 633 | |
a37376e7 VS |
634 | if (grub_memcmp (args[0], "--md5", sizeof ("--md5")) != 0) |
635 | goto fail; | |
636 | if (argc == 1) | |
637 | goto fail; | |
638 | if (grub_strlen(args[1]) <= 3) | |
639 | goto fail; | |
640 | salt = args[1]; | |
641 | saltend = grub_strchr (salt + 3, '$'); | |
642 | if (!saltend) | |
643 | goto fail; | |
644 | pw = grub_malloc (sizeof (*pw)); | |
645 | if (!pw) | |
646 | goto fail; | |
647 | ||
648 | p = saltend + 1; | |
649 | for (i = 0; i < 5; i++) | |
650 | { | |
651 | int n; | |
652 | grub_uint32_t w = 0; | |
653 | ||
654 | for (n = 0; n < 4; n++) | |
655 | { | |
656 | int ww = ib64t(*p++); | |
657 | if (ww == -1) | |
658 | goto fail; | |
659 | w |= ww << (n * 6); | |
660 | } | |
661 | pw->hash[i == 4 ? 5 : 12+i] = w & 0xff; | |
662 | pw->hash[6+i] = (w >> 8) & 0xff; | |
663 | pw->hash[i] = (w >> 16) & 0xff; | |
664 | } | |
665 | { | |
666 | int n; | |
667 | grub_uint32_t w = 0; | |
668 | for (n = 0; n < 2; n++) | |
669 | { | |
670 | int ww = ib64t(*p++); | |
671 | if (ww == -1) | |
672 | goto fail; | |
673 | w |= ww << (6 * n); | |
674 | } | |
675 | if (w >= 0x100) | |
676 | goto fail; | |
677 | pw->hash[11] = w; | |
678 | } | |
679 | ||
680 | pw->saltlen = saltend - salt; | |
681 | pw->salt = (grub_uint8_t *) grub_strndup (salt, pw->saltlen); | |
682 | if (!pw->salt) | |
683 | goto fail; | |
684 | ||
e2830452 | 685 | return pw; |
a37376e7 VS |
686 | |
687 | fail: | |
688 | grub_free (pw); | |
e2830452 VS |
689 | return NULL; |
690 | } | |
691 | ||
692 | static grub_err_t | |
693 | grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), | |
694 | int argc, char **args) | |
695 | { | |
696 | struct legacy_md5_password *pw = NULL; | |
697 | ||
698 | if (argc == 0) | |
699 | return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected"); | |
700 | if (args[0][0] != '-' || args[0][1] != '-') | |
701 | return grub_normal_set_password ("legacy", args[0]); | |
702 | ||
703 | pw = parse_legacy_md5 (argc, args); | |
704 | ||
705 | if (pw) | |
706 | return grub_auth_register_authentication ("legacy", check_password_md5, pw); | |
707 | else | |
708 | /* This is to imitate minor difference between grub-legacy in GRUB2. | |
709 | If 2 password commands are executed in a row and second one fails | |
710 | on GRUB2 the password of first one is used, whereas in grub-legacy | |
711 | authenthication is denied. In case of no password command was executed | |
712 | early both versions deny any access. */ | |
713 | return grub_auth_register_authentication ("legacy", check_password_deny, | |
714 | NULL); | |
715 | } | |
716 | ||
717 | static grub_err_t | |
718 | grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)), | |
719 | int argc, char **args) | |
720 | { | |
721 | struct legacy_md5_password *pw = NULL; | |
722 | char entered[GRUB_AUTH_MAX_PASSLEN]; | |
723 | ||
724 | if (argc == 0) | |
725 | return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected"); | |
6e0632e2 | 726 | grub_puts_ (N_("Enter password: ")); |
e2830452 VS |
727 | if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) |
728 | return GRUB_ACCESS_DENIED; | |
729 | ||
730 | if (args[0][0] != '-' || args[0][1] != '-') | |
731 | { | |
732 | char correct[GRUB_AUTH_MAX_PASSLEN]; | |
733 | ||
734 | grub_memset (correct, 0, sizeof (correct)); | |
735 | grub_strncpy (correct, args[0], sizeof (correct)); | |
736 | ||
737 | if (grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) != 0) | |
738 | return GRUB_ACCESS_DENIED; | |
739 | return GRUB_ERR_NONE; | |
740 | } | |
741 | ||
742 | pw = parse_legacy_md5 (argc, args); | |
743 | ||
744 | if (!pw) | |
745 | return GRUB_ACCESS_DENIED; | |
746 | ||
747 | if (!check_password_md5_real (entered, pw)) | |
748 | return GRUB_ACCESS_DENIED; | |
749 | ||
750 | return GRUB_ERR_NONE; | |
a37376e7 VS |
751 | } |
752 | ||
57f20e67 VS |
753 | static grub_command_t cmd_source, cmd_configfile; |
754 | static grub_command_t cmd_source_extract, cmd_configfile_extract; | |
755 | static grub_command_t cmd_kernel, cmd_initrd, cmd_initrdnounzip; | |
756 | static grub_command_t cmd_password, cmd_check_password; | |
092fd48a VS |
757 | |
758 | GRUB_MOD_INIT(legacycfg) | |
759 | { | |
57f20e67 VS |
760 | cmd_source |
761 | = grub_register_command ("legacy_source", | |
762 | grub_cmd_legacy_source, | |
763 | N_("FILE"), | |
764 | N_("Parse legacy config in same context")); | |
765 | cmd_configfile | |
766 | = grub_register_command ("legacy_configfile", | |
767 | grub_cmd_legacy_source, | |
768 | N_("FILE"), | |
769 | N_("Parse legacy config in new context")); | |
770 | cmd_source_extract | |
771 | = grub_register_command ("extract_legacy_entries_source", | |
772 | grub_cmd_legacy_source, | |
773 | N_("FILE"), | |
5b1bdf12 | 774 | N_("Parse legacy config in same context taking only menu entries")); |
57f20e67 VS |
775 | cmd_configfile_extract |
776 | = grub_register_command ("extract_legacy_entries_configfile", | |
777 | grub_cmd_legacy_source, | |
778 | N_("FILE"), | |
5b1bdf12 | 779 | N_("Parse legacy config in new context taking only menu entries")); |
281d6905 | 780 | |
8fc6a271 VS |
781 | cmd_kernel = grub_register_command ("legacy_kernel", |
782 | grub_cmd_legacy_kernel, | |
783 | N_("[--no-mem-option] [--type=TYPE] FILE [ARG ...]"), | |
b525fd83 | 784 | N_("Simulate grub-legacy `kernel' command")); |
8fc6a271 VS |
785 | |
786 | cmd_initrd = grub_register_command ("legacy_initrd", | |
787 | grub_cmd_legacy_initrd, | |
788 | N_("FILE [ARG ...]"), | |
b525fd83 | 789 | N_("Simulate grub-legacy `initrd' command")); |
237a43b1 VS |
790 | cmd_initrdnounzip = grub_register_command ("legacy_initrd_nounzip", |
791 | grub_cmd_legacy_initrdnounzip, | |
792 | N_("FILE [ARG ...]"), | |
b525fd83 | 793 | N_("Simulate grub-legacy `modulenounzip' command")); |
237a43b1 | 794 | |
a37376e7 VS |
795 | cmd_password = grub_register_command ("legacy_password", |
796 | grub_cmd_legacy_password, | |
797 | N_("[--md5] PASSWD [FILE]"), | |
b525fd83 | 798 | N_("Simulate grub-legacy `password' command")); |
e2830452 VS |
799 | |
800 | cmd_check_password = grub_register_command ("legacy_check_password", | |
801 | grub_cmd_legacy_check_password, | |
802 | N_("[--md5] PASSWD [FILE]"), | |
b525fd83 | 803 | N_("Simulate grub-legacy `password' command in menuentry mode")); |
e2830452 | 804 | |
092fd48a VS |
805 | } |
806 | ||
807 | GRUB_MOD_FINI(legacycfg) | |
808 | { | |
809 | grub_unregister_command (cmd_source); | |
810 | grub_unregister_command (cmd_configfile); | |
57f20e67 VS |
811 | grub_unregister_command (cmd_source_extract); |
812 | grub_unregister_command (cmd_configfile_extract); | |
813 | ||
8fc6a271 VS |
814 | grub_unregister_command (cmd_kernel); |
815 | grub_unregister_command (cmd_initrd); | |
237a43b1 | 816 | grub_unregister_command (cmd_initrdnounzip); |
57f20e67 | 817 | |
a37376e7 | 818 | grub_unregister_command (cmd_password); |
e2830452 | 819 | grub_unregister_command (cmd_check_password); |
092fd48a | 820 | } |