~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to grub-core/commands/legacycfg.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Robert Millan, Updated translations
  • Date: 2010-11-22 12:24:56 UTC
  • mfrom: (1.26.4 upstream) (17.3.36 sid)
  • mto: (17.3.43 sid)
  • mto: This revision was merged to the branch mainline in revision 89.
  • Revision ID: james.westby@ubuntu.com-20101122122456-y82z3sfb7k4zfdcc
Tags: 1.99~20101122-1
[ Colin Watson ]
* New Bazaar snapshot.  Too many changes to list in full, but some of the
  more user-visible ones are as follows:
  - GRUB script:
    + Function parameters, "break", "continue", "shift", "setparams",
      "return", and "!".
    + "export" command supports multiple variable names.
    + Multi-line quoted strings support.
    + Wildcard expansion.
  - sendkey support.
  - USB hotunplugging and USB serial support.
  - Rename CD-ROM to cd on BIOS.
  - Add new --boot-directory option to grub-install, grub-reboot, and
    grub-set-default; the old --root-directory option is still accepted
    but was often confusing.
  - Basic btrfs detection/UUID support (but no file reading yet).
  - bash-completion for utilities.
  - If a device is listed in device.map, always assume that it is
    BIOS-visible rather than using extra layers such as LVM or RAID.
  - Add grub-mknetdir script (closes: #550658).
  - Remove deprecated "root" command.
  - Handle RAID devices containing virtio components.
  - GRUB Legacy configuration file support (via grub-menulst2cfg).
  - Keyboard layout support (via grub-mklayout and grub-kbdcomp).
  - Check generated grub.cfg for syntax errors before saving.
  - Pause execution for at most ten seconds if any errors are displayed,
    so that the user has a chance to see them.
  - Support submenus.
  - Write embedding zone using Reed-Solomon, so that it's robust against
    being partially overwritten (closes: #550702, #591416, #593347).
  - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged
    into a single GRUB_DISABLE_RECOVERY variable.
  - Fix loader memory allocation failure (closes: #551627).
  - Don't call savedefault on recovery entries (closes: #589325).
  - Support triple-indirect blocks on ext2 (closes: #543924).
  - Recognise DDF1 fake RAID (closes: #603354).

[ Robert Millan ]
* Use dpkg architecture wildcards.

[ Updated translations ]
* Slovenian (Vanja Cvelbar).  Closes: #604003
* Dzongkha (dawa pemo via Tenzin Dendup).  Closes: #604102

Show diffs side-by-side

added added

removed removed

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